這篇來看看能改變 JavaScript 中 this 的三種方法:就是標題的 call()
、apply()
、bind()
。
接下來會使用下面的例子:
const person = {
name: 'Peter'
}
function sayHi(){
console.log(`Hi, ${this.name}`)
}
sayHi() // Hi, Peter
透過這三種方法,讓 sayHi()
這個函式改變 this 指向,印出 Hi, Peter。
先上語法:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
使用 bind
需要注意:
bind
會建立一個新的函式,需要額外執行。this
會綁定到第一個參數。實際寫法為:
const sayHiPeter = sayHi.bind(person)
sayHiPeter() // Hi, Peter
或是直接接到函式後方:
const sayHiPeter = function sayHi(){
console.log(`Hi, ${this.name}`)
}.bind(person)()
bind
可以綁定傳入函式的參數。 可以選擇將參數寫死,或是自行傳入,先將程式碼改一下:
const person = {
name: 'Peter'
}
// 需要傳入 age 和 sex 兩個參數
function sayHi(age, sex){
console.log(`Hi, ${this.name}`)
console.log(age, sex)
}
const sayHiPeter = sayHi.bind(person, 12, "male")
sayHiPeter()
// 印出 peter, 12, male
const sayHiPeter = sayHi.bind(person)
sayHiPeter(12, "male")
// 印出 peter, 12, male
兩者差別在於,使用方法 1 後,不論之後如何更改值都無法被改變。
而這兩個與 bind
的主要差異為:call
& apply
會直接執行函式。
兩者的語法為:
// apply()
fun.apply(thisArg, [argsArray])
// call()
fun.call(thisArg, arg1, arg2, ...)
this
指向。apply
與 call
的差異在於傳入的函式參數不一樣,apply
需要傳入陣列。使用 call
:
sayHi.call(person, 12, "male")
// 印出 peter, 12, male
使用 apply
(傳遞陣列):
sayHi.apply(person, [12, "male"])
// 印出 peter, 12, male
來嘗試改變物件中函式的指向:
const fruit = {
fruitName: 'apple',
getFruitName: function () {
console.log(this.fruitName)
}
}
fruit.getFruitName()
// 印出 apple
這時候再建立一個 someFruit
,並把原本 fruit
中的函式指向它。
const someFruit = {
fruitName: 'banaba'
}
fruit.getFruitName.call(someFruit)
// banana