为什么 call.call 调用函数

why call.call invokes function

在这里,如果我有一个记录 "called my function"

的函数

function myFunction() {
  console.log('called my function')
}

Function.prototype.call.call(myFunction) // => "called my function"

而在单个 call 喜欢:

function myFunction() {
  console.log('called my function')
}
Function.prototype.call(myFunction)

一点背景:

call 是属于 Function 对象的函数,您可能知道。

所以如果我们有这个函数:(注意 this

function invite(where) {
   alert ("hi "+this.name+" do you want come to "+where);
}

和这个对象:

var obj = { name:"PETER" }

我们可以做到

invite.call(obj, "the cinema")
  • 要调用的第一个参数是 CONTEXT。该函数将在该对象的上下文中执行,这就是为什么警报将显示 "PETER" for this.name

  • 的原因
  • 第二个参数等等都是参数,所以alert会显示"the cinema"。

第二种情况:Function.prototype.call.call

Function.prototype.call 是函数对象的原始 "call" 函数。所以你直接访问这个函数,并想为你的对象调用它 ("call the function call"):

 Function.prototype.call.call

您希望在函数 myFunction 的上下文中调用函数 "call"(首次调用参数):

 Function.prototype.call.call(myFunction, ...);

也就是说,实际上相当于

 nyFunction.call(...);

第一个案例

第一种情况什么都不做,因为原型本身就是一个函数(你可以“.call”:),所以

Function.prototype.call(whatever)

等同于

Function.prototype();

在您的函数上下文中执行

简而言之,call 本身不期望函数作为参数,也不会将它的参数作为函数调用:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

相反,call 是在其 prototype 中定义的所有 Function 对象的成员函数,它使您能够在传递要使用的参数时调用成员函数的特定实现作为函数调用中的 this。由于 call 本身是一个 Function,它也有一个 call member 函数。

其中一个用例是 super 概念的仿真,例如Java。考虑另一个函数不是 call:

的例子

function Foo() {
  console.log('Foo');
}

Foo.prototype.bar = function () {
    console.log('Foo bar');
};

function Baz() {
    console.log('Baz');
}

Baz.prototype = Object.create(Foo.prototype);

Baz.prototype.bar = function () {
    Foo.prototype.bar.call(this);
        // Call the super class implementation of `bar`
    console.log('Baz bar');
};

var baz = new Baz();
baz.bar();

当你写someFunction.call(foo)时,意味着调用someFunction同时传递foo作为this参数。通常你有 someObject.someFunction(),它将 someObject 作为 this 隐式传递,但是使用 .call 你可以将 this 设置为任何你想要的。参见 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

那么Function.prototype.call(myFunction)是做什么的呢?嗯,它调用 Function.prototype,将 myFunction 作为 this 传递。调用 Function.prototype 有什么作用?根据 ECMA 规范:

The Function prototype object is itself a Function object (its [[Class]] is "Function") that, when invoked, accepts any arguments and returns undefined.

这就是为什么 Function.prototype.call(myFunction) 没有明显效果。

另一方面,Function.prototype.call.call(myFunction) 调用 Function.prototype.call(它本身就是一个函数!),将 myFunction 作为 this 传递。这是做什么的?和myFunction.call()完全一样:当你查找一个函数对象的call属性时,你无论如何都是从Function.prototype中获取的(通过对象继承)。那么这是做什么的呢?它调用 myFunction 时没有(正常)参数,但它看到的 this 的值有点棘手:如果函数处于严格模式,this 将是 undefined ;如果它是非严格的,this 将是全局对象(a.k.a。window 在浏览器中)。

这也与您从 myFunction() 获得的行为相同(即不在对象上调用它)。换句话说, Function.prototype.call.call(foo) 只是一种(非常)迂回的写法 foo().