关于js call原理问题?

function fn1(){console.log(1);}
function fn2(){console.log(2);}

**fn1.call(fn2);//输出1
fn1.call.call(fn2);//输出2**


fn1.call(fn2);//输出1 我基本上能理解

首先fn1通过原型链查找机制找到Function.prototype上的call方法,并且让call方法执行,此时call这个方法中的this就是要操作的fn1。在call方法代码执行的过程过程中,首先让fn1中的“this关键字”变为fn2,然后再让fn1这个方法执行。

fn1.call.call(fn2);//输出2 我始终没有摸透 网上的文章看了不少也没有搞懂 反应越乱了

我的理解为将fn1.call当作一个整体 还是fn1通过原型找到call方法 call方法也是函数 在通过原型找到call方法并让call执行 将fn1.call中的关键字改为 fn2 并让 fn1.call执行 此时为什么就变为fn2执行了   ?
阅读 2.8k
4 个回答

开始我也没有理解 在写个过程中逐渐理解了
你可以先模拟一下 call,尝试使用call2来解释

Function.prototype.call2 = function(context, ...args) {
    context = context || window;
    context.fn = this;
    const result = context.fn(...args);
    delete context.fn;
    return result;
};

第一个,第二个都是按照你的方式输出。模拟是成功的。
我们来看第二个

fn1.call2 === fn1.call2.call2 // true

则其实是

fn1.call2 === fn1.call2.call2 === Function.prototype.call2 

其实调用方式为 Function.prototype.call2.call2(fn2)
至于为什么会被实质上是 当前 fn2 被当作this 指向了call。和fn1 一点关系也没有

最后发现实际写的 call2 一点用没有,发上去权当测试。

你说的很接近,但是应该是
从原型链拿到了Function.prototype.call的引用,而不是fn1.call

所以这个问题会变成(Function.prototype.call).call(fn2)

这样应该就比较好理解Function.prototype.call(thisArg)

Function.prototype.call调用传入第一个需要充当this的函数

我们把fn2稍微改一下

function fn2(test){ console.log('fn2: ' + test); console.log(this)}

此时fn1.call.call(fn2)

会输出fn2: undefined 以及window对象

是因为我们call(fn2) === call(fn2, void 666, void 666)

稍微改动一下

fn1.call.call(fn2, {}, 'fn2 test case')
会输出fn2: fn2 test case 以及{}

fn.call(bla) 相当于调用 bla.call()

所以 fn1.call(fn2) 相当于调用 fn2.call()。做个实验

function fn1() {
    console.log(1, this.name);
}

function fn2() {
    console.log(2, this.name);
}

调用 fn1.call(fn2) 会输出 1 "fn2",也就是说,执行的是 fn1,但其 this 指向是 fn2(这里把 fn2 看作一个对象)

接下来,fn1.call.call(fn2),这里相当于是调用了 Function.prototype.call.call(fn2),或者说,是调用了 fn2.call()——因为它是调用的是第一个 call,而把它的 this 指向了 fn2

这个调用结果是 2 ""

我的猜测如下:

fn1.call.call(fn2):相当于执行fn1.call(),并把该函数fn1.call内部的this指向fn2;
由于fn1.call 就是 fn1.__proto__.call 就是 Function.prototype.call;
所以就相当于执行Function.prototype.call(),并把该函数Function.prototype.call内部的this指向fn2;
Function.prototype.call方法需要一个函数作为 this,并调用这个this函数。所以当 this 被设置为 fn2 时,实际上是在调用 fn2 这个函数。
所以fn1.call.call(fn2)就相当于执行fn2()函数。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题