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)));
}
};