今天在讀程序題的時候,遇到call,apply,bind的使用。
const person = { name: 'Lydia' }
function sayHi(age) {
console.log(`${this.name} is ${age}`)
}
sayHi.call(person, 21)
sayHi.bind(person, 21)
一、談一下上述三者的使用目的:三者都是用來改變this的指向。
二、三者分別是如何定義的及區別(摘自MDN):
apply()
方法調用一個具有給定this
值的函數,以及作爲一個數組(或類似數組對象)提供的參數。
MDN關於apply詳細介紹:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
注意:call()方法的作用和 apply() 方法類似,區別就是call()
方法接受的是參數列表,而apply()
方法接受的是一個參數數組。
bind()
方法創建一個新的函數,在調用時設置this
關鍵字爲提供的值。並在調用新函數時,將給定參數列表作爲原函數的參數序列的前若干項。
MDN關於bind詳細介紹:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
call()
方法使用一個指定的 this
值和單獨給出的一個或多個參數來調用一個函數。
MDN關於call詳細介紹:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call
注意:該方法的語法和作用與 apply()
方法類似,只有一個區別,就是 call()
方法接受的是一個參數列表,而 apply()
方法接受的是一個包含多個參數的數組。
三、在程序中收穫
<script>
var name = 'Lily',
age = 13
var obj = {
name: 'Sam',
objAge: this.age,
myFunc: function (param1, param2) {
console.log(this.name + ' ' + this.objAge + ' ' + this.age + ' ' + param1 + ' ' + param2)
// Sam 13 undefined 1 2
}
}
obj.myFunc(1, 2)
</script>
非常明確,在obj.myFunc()中,通過this.age是獲取不到定義在window中的age值,因爲在該方法中,this指向的是obj對象。因此值爲undefined,這個時候,可以通過call,apply,bind來更改this的指向,從而獲取值。
<script>
var name = 'Lily',
age = 13
var obj = {
name: 'Sam',
objAge: this.age,
myFunc: function (param1, param2) {
console.log(this.name + ' ' + this.objAge + ' ' + this.age + ' ' + param1 + ' ' + param2)
// Amy 20 21 1 2
}
}
var db = {
name: 'Amy',
age: 21,
objAge: 20
}
obj.myFunc.call(db, '1', '2') // db爲this要指向的對象,後面傳入的是參數列表,參數可以是任意類型,當第一個參數爲null、undefined的時候,默認指向window;
obj.myFunc.apply(db, [1, 2]) // db爲this要指向的對象,參數必須放在一個數組裏面;
obj.myFunc.bind(db, '1', '2')() // db爲this要指向的對象,返回的是一個新函數,必須調用纔會去執行。
</script>
四、上述三者的具體應用:
轉自:https://blog.csdn.net/wyyandyou_6/article/details/81488103
另:用 apply
將數組添加到另一個數組
我們可以使用push
將元素追加到數組中。並且,因爲push接受可變數量的參數,我們也可以一次推送多個元素。但是,如果我們傳遞一個數組來推送,它實際上會將該數組作爲單個元素添加,而不是單獨添加元素,因此我們最終得到一個數組內的數組。如果那不是我們想要的怎麼辦?在這種情況下,concat
確實具有我們想要的行爲,但它實際上並不附加到現有數組,而是創建並返回一個新數組。 但是我們想要附加到我們現有的陣列......那麼現在呢? 寫一個循環?當然不是嗎?
var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
最後迴歸最初的讀程序,結果是
Lydia is 21
function
undefined
使用這兩種方法,我們都可以傳遞我們希望 this
關鍵字引用的對象。但是,.call
是立即執行的。
.bind
返回函數的副本,但帶有綁定上下文!它不是立即執行的。