call函数可以实现对函数this的显示绑定。将一个函数的this指向显示的绑定到某一个指定的对象上,并运行这个函数。
本来呢我们写的函数默认是挂载在window对象实例上面的,如果直接调用函数那么函数内部的this就会通过默认绑定绑定到了window上。
function fun() {
console.log(arguments);
console.log(this.name);
};
console.log(window.fun);
-------------------------------------------------
ƒ fun(){
console.log(arguments);
console.log(this.name);
}
那么call和apply采用的思想就是把这个函数也挂载一份到我们这个目标对象身上。然后call函数真正执行的是目标对象身上的一个方法而不是我们之前定义的函数挂载在window身上的那个函数,虽热两者的内容一样,但是二者的this指向完全不同
// 手写call
// call函数负责将函数的this绑定到指定的对象,并执行这个函数一次
// call接受一个上下文对象, 同时接受函数调用所需的参数列表
Function.prototype._call = function(ctx,...args){
// 如果没有传入ctx那么默认就采用window
ctx=ctx||window;
// 第一步,把这个函数,变成我们指定的这个上下文对象的方法,也称为挂载
ctx.fn = this;
// 第二步,执行ctx的fn方法,显然这个时候ctx.fn中的this肯定指向ctx(隐式绑定)
ctx.fn(...args);
// 第三步,因为平白无故在ctx上加了一个属性fn,所以最后应该把这个属性删除掉
delete ctx.fn;
}
// 手写apply
// apply和call基本都是一样的,唯一区别就是,apply接受的是一个数组,数组里面放的是参数,而call接受的就是参数列表
Function.prototype._apply = function(ctx,args=[]){
// 如果没有指定ctx,就挂载到window
ctx= ctx||window;
// 然后往ctx上也挂载一份这个函数
ctx.fn = this;
// 然后执行以下这个函数
// 将数组展开成参数列表
ctx.fn(...args);
// 最后删除这个属性
delete ctx.fn;
}