- 由於
call()
、apply()
與bind()
都是屬於Function.prototype
對象下的方法,所以每個function
實例都擁有有call
、apply
與bind
屬性。 - 相同點:都是爲改變
this
指向而存在的。 - 異同點:使用
call()
方法時,傳遞給函數的參數必須逐個列舉出來,使用apply()
方法時,傳遞給函數的是參數數組。bind()
和call()
很相似,第一個參數是this
的指向,從第二個參數開始是接收的參數列表。bind()
方法不會立即執行,而是返回一個改變了上下文this
後的函數,用於稍後調用。call()
、apply()
則是立即調用。
1、call實現原理:
Function.prototype.mycall = function (context) {
// 當context爲null時,其值則爲window
context = context || window;
// this爲調用mycall的函數。將this賦值給context的fn屬性
context.fn = this;
// 將arguments轉爲數組,並從下標1位置開如截取
let arg = [...arguments].slice(1);
// 將arg數組的元素作爲fn方法的參數執行,結果賦值給result
let result = context.fn(...arg);
// 刪除fn屬性
delete context.fn;
// 返回結果
return result;
}
測試:
function add(c, d){
return this.a + this.b + c + d;
}
var obj = {a:1, b:2};
console.log(add.mycall(obj, 3, 4)); // 10
2、apply實現原理
Function.prototype.myapply = function (context) {
// 當context爲null時,其值則爲window
context = context || window
// this爲調用myapply的函數。將this賦值給context的fn屬性
context.fn = this;
// 如果未傳值,則爲一空數組
let arg = arguments[1] || [];
// 將arg數組的元素作爲fn方法的參數執行,結果賦值給result
let result = context.fn(...arg);
// 刪除fn屬性
delete context.fn
// 返回結果
return result
}
測試:
function add(c, d){
return this.a + this.b + c + d;
}
var obj = {a:1, b:2};
console.log(add.myapply(obj, [5, 6])); // 14
3、bind實現原理
Function.prototype.mybind = function (context) {
// this爲調用mybind的函數。將this賦值給變量_this
let _this = this;
// 將arguments轉爲數組,並從下標1位置開如截取
let arg = [...arguments].slice(1);
// 返回函數fn
return function fn(){
// 通過apply方法調用函數並返回結果。
return _this.apply(context, arg.concat(...arguments));
}
}
測試:
var obj = {
siteName: "zhangpeiyue.com"
}
function printSiteName() {
console.log(this.siteName);
}
var site = printSiteName.mybind(obj);
// 返回的是一個函數
console.log(site) // function () { … }
// 通過mybind使其this發生了變化
site();// zhangpeiyue.com
—————END—————
喜歡本文的朋友們,歡迎關注公衆號 張培躍,收看更多精彩內容!!!公衆號回覆 電子書 ,送你經典電子書籍!