call和apply、bind都是為了改變this指向的;區別只是傳參方式不同;
- call可以接收參數列表
fun.call(thisArg, arg1, arg2, ...)
- apply只接受一個參數的數組
fun.apply(thisArg, [argsArray])
- bind不會立即執行
func.bind(thisArg[, arg1[, arg2[, ...]]])
call的實現
Function.prototype.myCall = function(context){
var context = context || windows; //沒有指向傳入的話默認為windows的上下文
context.fn = this; //思路是:由於改變指向;讓新的對象可以執行這個函數,那么可以考慮給新的對象添加一個函數;然后在執行完之后刪除這個函數
var args = [...arguments].slice(1); //取出context后面的參數;對應call的傳參方式
var result = context.fn(...args);
delete context.fn;
return result;
}
apply的實現
apply的實現其實是和call類似的;知識由於傳參方式不一樣;取得參數傳給fn的時候的方式也是不一樣的
Function.prototype.apply = function(context){
var context = context || windows;
context.fn = this;
var result;
if(arguments[1]){ //判斷是否有第二個參數
result = context.fn(...arguments[1])
}else{
result = context.fn()
}
delete context.fn
return result;
}
簡要call和apply的實現步驟:
bind方法的實現
Function.prototype.myBind = function() {
var _this = this;
var context = [].shift.call(arguments);// 保存需要綁定的this上下文;注意shift方法將第一個元素去除了;所以后面直接將剩下的arguments中的參數取出來即可;保存了指向的上下文
var args = [].slice.call(arguments); //剩下參數轉為數組
console.log(_this, context, args);
return function() { //bind方法返回的是一個方法
return _this.apply(context, [].concat.call(args, [].slice.call(arguments)));
}
};