为什么我不能 var a = someFn.call;一种();?

Why can't I var a = someFn.call; a();?

这似乎是矛盾的...在 Chrome 控制台中:

> var forEach = Array.prototype.forEach.call;

> forEach
  function call() { [native code] }

> Object.getPrototypeOf(forEach);
  function () {}

> forEach([1,2,3], function(a) { console.log(a); });
  Uncaught TypeError: forEach is not a function

我猜在 JS 内部 function.call 不完全像普通函数一样对待?

在 JavaScript 中,函数首先是 class 公民,就像字符串和整数一样。当您这样做时,Array.prototype.forEach.call,您将获得 .call 属性 的 ,在 prototype 链上向上是 Function.prototype.call。因此,您的 forEach 变量设置为 Function.prototype.call.

现在,当您调用 一个函数时,该函数内部 this 的值取决于它的调用方式。当你做 forEach(...) 时,就像做 Function.prototype.call.call(null) 一样。 call 期望 this 是一个函数,但它不是,所以它会抛出一个错误。

您可能需要以下内容:

var forEach = Array.prototype.forEach;
forEach.call([1,2,3], function(a) { console.log(a); });

或者也许:

var forEach = Array.prototype.forEach.bind([1,2,3]);
forEach(function(a) { console.log(a); });

如果你想这样做,你也可以这样做forEach(array, fn)

var forEach = Function.call.bind(Array.prototype.forEach);

现在您可以像以前一样使用它了:

forEach([1,2,3], function(a) { console.log(a); });

您正在做的是将调用 this 绑定到 Array.prototype.forEach。这只是一个shorthand写成Array.prototype.forEach.call.

如果你想象如何调用 "invokes" 函数会更容易,所以想象调用函数是这样做的(实际上不是这样的):

return this(arg1, arg2, etc);

现在假设 bind returns 调用函数绑定 thisArray.prototype.forEach.call:

return Array.prototype.forEach.call(arg1, arg2, etc);

你当然可以自己做同样的事情:

var forEach = function(array, fn) {
    return Array.prototype.forEach.call(array, fn);
}

虽然我不确定哪个更好,但性能方面。

内部依赖于 this 的函数在与 "owner" 分离时必须绑定才能正常工作,因为对于未绑定的函数,this 值将是左侧引用的对象- obj.func() 中点的一侧。如果直接从当前范围调用函数(例如 func()),则 this 将指向 window.

因此在下面的代码中调用 forEach 时的 this 值将是 window 而你需要它是 Array.prototype.forEach.

var forEach = Array.prototype.forEach.call;

forEach([1, 2], function () {}); //this inside forEach is window

要解决这个问题,我们可以将 call 绑定到 Array.prototype.forEach

   var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);

   forEach([1, 2, 3], function (num) {
       console.log(num);
   });