bind 和 call/apply 同樣,都是用來改變上下文 this 指向的,不一樣的是,call/apply 是直接使用在函數上,而 bind 綁定 this 後返回一個函數(閉包) call和apply的惟一區別是call的除了第一個參數是綁定上下文,能夠傳多個參數,apply的第一個參數是綁定上下文,第二個參數是一個數組 calljavascript
Function.prototype.myCall = function(context) {
// 處理第一個參數傳null或者undfined,這時將上下文綁定到window對象上
context = context || window;
context._fn = this;
let args = [...arguments].slice(1);
let result = context._fn(...args);
delete context._fn;
return result;
}
複製代碼
applyjava
Function.prototype.myApply = function(context) {
context = context || window;
context._fn = this;
let args = [...arguments].slice(1); // 第二個參數是數組
let result = context._fn(...args);
delete context._fn;
return result;
}
複製代碼
bind數組
Function.prototype.myBind = function(context) {
let self = this;
let args = [...arguments].slice(1);
return function() {
let newArgs = [...arguments];
return self.apply(context, args.concat(newArgs))
}
}
複製代碼
可是做爲構造函數試用的時候會出錯,構造函數的this綁定在實例上,除此以外,還須要解決原型丟失的問題閉包
Function.prototype.myBind = function(context) {
let self = this;
let args = [...arguments].slice(1);
var bound = function() {
let newArgs = [...arguments];
// 做爲構造函數使用
if(this instanceof bound) {
return self.apply(this, args.concat(newArgs))
} else {
return self.apply(context, args.concat(newArgs))
}
}
// 維護原型關係
if(this.prototype) {
bound.prototype = this.prototype;
}
return bound;
}
複製代碼