为什么我不能改变a = someFn.call;一个();?

时间:2015-10-01 17:25:37

标签: javascript prototype call typeerror

这在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的处理方式与普通函数不完全相同吗?

3 个答案:

答案 0 :(得分:3)

如果您想forEach(array, fn)

,也可以这样做
var forEach = Function.call.bind(Array.prototype.forEach);

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

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

您正在做的是将this绑定到Array.prototype.forEach。这只是写Array.prototype.forEach.call的简写。

如果你想象出调用“调用”函数的方式会更容易,所以想象调用函数会这样做(实际上不是这样):

return this(arg1, arg2, etc);

现在假设bind返回调用函数,绑定为thisArray.prototype.forEach.call

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

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

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

虽然我不确定哪一个会更好,但性能明智。

答案 1 :(得分:2)

在JavaScript中,函数是一等公民,就像字符串和整数一样。当您执行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); });

或者也许:

{{1}}

答案 2 :(得分:2)

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

因此,在下面的代码中,forEach在调用window时将Array.prototype.forEachvar forEach = Array.prototype.forEach.call; forEach([1, 2], function () {}); //this inside forEach is window ,而您需要call。{/ p>

Array.prototype.forEach

要解决该问题,我们可以将 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); forEach([1, 2, 3], function (num) { console.log(num); }); 绑定到def exact_change( target_amount, L ): if target_amount > sum(L): return False elif target_amount == 0: return True elif target_amount < 0: return False elif target_amount > 0 and L==[]: return False elif target_amount == L: return True else: loseit = exact_change(target_amount, L[1:]) useit = exact_change(target_amount, L[0]) return loseit or useit'

>>> exact_change( 42, [25, 1, 25, 10, 5, 1] )
True
>>> exact_change( 42, [25, 1, 25, 10, 5] )
False
>>> exact_change( 42, [23, 1, 23, 100] )
False
>>> exact_change( 42, [23, 17, 2, 100] )
True
>>> exact_change( 42, [25, 16, 2, 15] )
True  # needs to be able to "skip" the 16...
>>> exact_change( 0, [4, 5, 6] )
True
>>> exact_change( -47, [4, 5, 6] )
False
>>> exact_change( 0, [] )
True
>>> exact_change( 42, [] )
False