为什么我不能 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 调用函数绑定 this
到 Array.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);
});
这似乎是矛盾的...在 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 调用函数绑定 this
到 Array.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);
});