JavaScript 中的 call, apply, bind 這三個函數的做用和區別在各大論壇都被討論了不少次了,可是我一直都還沒來得及好好總結,此次正好看到了一個很不錯的關於JavaScript 中 apply 、call 的詳解,本身就學習並總結了一波~,正好更新一波博客😂javascript
其實 call 和 apply 的做用很明確,就是要經過對它們傳入的參數來肯定函數上下文的對象,也就是經過參數來肯定函數中的 this 關鍵字的指向,this 關鍵字是 JavaScript 中一個很重要、很值得咱們去加深學習和理解的東西,具體關於 this 的知識總結,我之前寫了一個博客,感興趣的話請參考淺析JavaScript中的this關鍵字。java
call 和 apply 的做用是相同的,它們的惟一區別就是對傳入參數的格式要求不一樣。git
call()
github
call
方法在調用的時候,須要傳入一個函數的上下文對象和一個參數列表數組
let obj = {
name: 'nicole'
}
let func = function (){
console.log(this.name)
console.log(arguments)
}
func.call(obj,{age: '20'},{id: '1'})
// 運行結果是打印出 nicole 和 [{age: "20"},{id: '1'}]
複製代碼
函數的上下文被指向了傳入的第一個參數obj,若是咱們直接調用func(obj,{age: '20'},{id: '1'})
,那麼函數的 this 則指向了 window (嚴格模式下爲 undefined)。app
apply()
函數
apply
方法在調用的時候,須要傳入一個函數的上下文對象和一個數組學習
let obj = {
name: 'nicole'
}
let func = function (){
console.log(this.name)
console.log(arguments)
}
func.apply(obj,[{age: '20'},{id: '1'}])
// 運行結果是打印出 nicole 和 [{age: "20"},{id: '1'}]
複製代碼
因爲call
和apply
方法的做用都是同樣的,因此在決定究竟要用哪一個的時候,咱們能夠直接從參數的形式來考慮,若是咱們要傳入的參數是數組,那咱們就直接使用apply
就好。ui
與call
和apply
方法不一樣的是,call
和apply
方法在被調用時就直接執行了當前的函數,而bind
直接返回了一個改變了函數上下文以後的新函數,這個新函數與原函數並不是是同一個函數,並且與call
相似,bind
方法接受列表形式的參數this
let obj = {
name: 'nicole'
}
let func1 = function (){
console.log(this)
}
let func2 = func1.bind(obj,{age: '20'})
func1 === func2 // false
func2() // {name: "nicole"}
複製代碼
咱們能夠本身實現一個bind
函數
Function.prototype.bindTest = function () {
let self = this;
let context = Array.prototype.shift.call(arguments);
let arg = Array.prototype.slice.call(arguments);
return function () {
self.apply(context, [...arg, ...arguments]);
}
}
let obj = {
name: 'nicole'
}
let func1 = function () {
console.log(this);
console.log(arguments);
}
let func2 = func1.bindTest(obj)
func2({age: 11});
// 運行結果 {name: "nicole"} [{age: 11}]
複製代碼
值得注意的是,bind
方法返回的函數裏面的 this 值不能夠再被改變了,也就是說不能再修改函數的上下文,無論再對函數調用call
仍是apply
,都沒法再改變函數的上下文。而普通的函數則能借助call
仍是apply
各類肆意的修改函數的上下文。
let obj1 = {
name: 'nicole'
}
let obj2 = {
name: 'neil'
}
let func = function (){
console.log(this)
}
let func1 = func.bind(obj1)
func1.call(obj2)
// 運行結果是{name: "nicole"},也就是說雖然調用了func1的 call 方法,可是函數上下文依然是obj1
func.call(obj1) // {name: "nicole"}
func.call(obj2) // {name: "neil"}
func.apply(obj1) // {name: "nicole"}
func.apply(obj2) // {name: "neil"}
複製代碼