call 是JS 中常用的一个方法
官方解释是”调用一个对象的一个方法,以另一个对象替换当前对象”
不久前看到一个call.call 方法
心中充满疑惑,便想详细分析一下
举个栗子
function fn1() {
console.log("fn1 this: "+ this);
}
function fn2() {
console.log("fn2 this: "+ this);
}
fn1();
fn2();
// fn1 this: [object Window]
// fn2 this: [object Window]复制代码
这是两个正常执行的函数,他们的this 都是window
function fn1() {
console.log("fn1 this: "+ this);
}
function fn2() {
console.log("fn2 this: "+ this);
}
fn1.call(fn2);
// fn1 this: function fn2() {
console.log("fn2 this: "+ this);
}复制代码
这里显然执行的还是fn1 ,但是fn1 的this 变成了 fn2
虽然改变了fn1 的this 但fn1 还是正常的执行了
function fn1() {
console.log("fn1 this: "+ this);
}
function fn2() {
console.log("fn2 this: "+ this);
}
fn1.call.call(fn2);
// fn2 this: [object Window]复制代码
通过输出可以看出,显然fn1 没有执行,这次执行的fn2
this 是window
核心问题来了: 为什么两个call 放在一起后,没有执行原方法,而是执行了传入的方法
我们来慢慢理一下 fn1.call.call(fn2) 的执行过程
1:这个方法是在哪开始执行的 call(fn2)
2:执行后的结果是什么 call(fn2) 前面的this 改成了fn2 前面方法照常执行
3:call(fn2) 前面是什么,改变this 后会怎样 call(fn2) 前面是fn1.call 改变this 后 由于fn1是这次的行为主体(this),是他执行了call 方法,所以fn1 被call(fn2) 变成了 fn2,所以接下来执行的就是 fn2.call()
4:输出 fn2 this: [object Window]
function fn1() {
console.log("fn1 this: "+ this);
}
function fn2() {
console.log("fn2 this: "+ this);
}
fn1.call.call.call(fn2);复制代码
1:执行过程是call(fn2)执行 前面的主体this 变成fn2
2:fn1.call.call 的主体(this)是 fn1.call (是fn1.call 执行了call 方法) 所以fn1.call变成fn2
3:接下来执行的就是 fn2.call()
总结
就是说只要一个方法中call 出现两次或者两次以上,他都会在第二步,把前面的行为主体变成你传入的参数(第一个),然后让其执行call()
所以fn1.call.call(fn2) 其实就等于 fn1.call. … .call(fn2) 等于fn2()