JS中的call与call.call

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()

虽然结局有点尴尬,思路就是这样,如果有问题,或者更好的理解方法请留言告诉我,感谢

关于行为主体的寻找方式,可以看下我的这篇笔记 This

发表评论

电子邮件地址不会被公开。 必填项已用*标注