问一个有关Nodejs中call的问题

问一个有关Nodejs中call的问题

function f1()
{
console.log(this);
console.log(1); } function f2(){
console.log(this);
console.log(2) } f1.call.call(f2);  //Window,2

今天研究了一下call,但是f1.call.call(f2);  //Window,2这里实在是有点不懂,为啥是这样的结果勒?

求大神解析。


5 回复

好的,让我们来详细分析一下你提到的代码片段,并解释为什么会出现那样的输出结果。

代码片段

function f1() {    
    console.log(this);    
    console.log(1);
}

function f2() {    
    console.log(this);    
    console.log(2);
}

f1.call.call(f2); // Window,2

解析

call 是 JavaScript 中的一个函数方法,它允许你在调用一个函数时显式地指定该函数内部的 this 值。call 方法的第一个参数就是作为函数内部 this 的对象。

逐步分析

  1. f1.call

    • 这里 f1.call 返回的是一个函数,这个函数的作用是在调用时将 f1 函数的执行上下文(即 this)设置为传入的参数。
    • f1.call 可以被看作是一个新的函数,我们假设这个新函数为 newFn
  2. newFn.call(f2)

    • 现在 newFn.call(f2) 被调用,这意味着 f1 函数将使用 f2 作为其内部的 this
    • 所以,实际上会执行 f1.call(f2)
  3. f1.call(f2)

    • 这里 f1.call(f2) 的意思是将 f1 函数的执行上下文(即 this)设置为 f2
    • 在浏览器环境中,如果 f1 没有明确的绑定,那么 this 通常指向全局对象 window
    • 因此,console.log(this) 输出 window 对象。
    • 接着,console.log(1) 输出数字 1
  4. f2()

    • 接下来,f1.call(f2) 完成后,继续执行 f2 函数。
    • f2 函数内部的 this 也会指向全局对象 window
    • 因此,console.log(this) 输出 window 对象。
    • 最后,console.log(2) 输出数字 2

示例代码

function f1() {
    console.log(this); // 输出 window 对象
    console.log(1); // 输出 1
}

function f2() {
    console.log(this); // 输出 window 对象
    console.log(2); // 输出 2
}

f1.call.call(f2); // Window, 2

结论

通过上述分析,我们可以看到 f1.call.call(f2) 实际上等价于 f1.call(f2),这导致了 f1 函数的 this 被设置为 f2,并且最终 f1f2 都会被执行。由于没有明确的 this 绑定,它们的 this 都指向了全局对象 window,因此输出结果为 Window, 2


method.call(f1) ~= f1.method();
Function.prototype.call ~= f1.call ~= f2.call;
f1.call.call(f2); ~= Function.prototype.call.call(f2) ~= f2.call();

真是脑筋急转弯。

$ node
> Function.prototype.call
[Function: call]
> Function.prototype.call.call
[Function: call]
> Function.prototype.call === Function.prototype.call.call
true

那个 f1 是个幌子。

(function(){}).call.call(f2)

结果一样

在Node.js中,call 方法用于调用一个函数,并显式指定该函数内部的 this 值。当你看到 f1.call.call(f2) 这样的代码时,实际上是在连续使用 call 方法。

让我们详细分析一下这个例子:

示例代码

function f1() {
    console.log(this);
    console.log(1);
}

function f2() {
    console.log(this);
    console.log(2);
}

f1.call.call(f2); // Window,2

分析

  1. f1.call: 这里的 f1.callFunction.prototype.call 的引用。call 方法需要一个参数来设置 f1 函数内部的 this 值。

  2. f1.call.call(f2): 这里实际上是 f1.call 被当作一个函数调用,其第一个参数为 f2。也就是说,f1.callthis 值被设置为 f2,然后 f1.call 会继续执行。

  3. f1.call 的实际调用:

    • f1.call 中的第一个参数 f2 将成为 f1this 值。
    • 因此,f1.call(f2) 实际上相当于 f1.call.call(null, f2)
  4. 最终调用:

    • f1 函数中的 console.log(this) 输出 f2(因为 this 等于 f2)。
    • 接着 console.log(1) 输出 1
  5. 全局上下文:

    • 由于 f1.call 没有显式绑定到任何对象,且在全局作用域中执行,因此 console.log(this) 输出的是全局对象(在浏览器中通常是 window 对象,在Node.js中通常是 global 对象)。
    • 所以输出为 Window, 2 或者在Node.js环境中可能是 global, 2

总结

  • f1.call.call(f2) 实际上是 f1.call(f2),其中 f2 成为 f1this 值。
  • f1 内部的 console.log(this) 输出 f2
  • f1 内部的 console.log(1) 输出 1
  • 最终 this 在全局上下文中输出为 global 对象。

希望这能帮助你理解这个现象!

回到顶部