为什么应用尚未绑定到Javascript中的函数?

时间:2014-04-15 17:47:27

标签: javascript prototype bind apply

为了这个问题,假设我希望能够在Javascript中创建一个函数,将一个数组的所有元素追加到另一个数组。实现这一目标的一种方法是,如果您有权访问目标数组,那就说:

var destination = [1,2,3];
var source = [4,5];
Array.prototype.push.apply(destination, source);
console.log(destination); // [1,2,3,4,5]

现在,由于Array.prototype.push.apply非常丑陋,我想将它别名为更好的东西,例如:

var pushAll = Array.prototype.push.apply;

我应该能够使用两个参数调用,即上下文(destination)和一个参数数组(source)。但是,当我尝试使用别名时,会发生这种情况:

pushAll(destination, [6,7]);
TypeError: Function.prototype.apply was called on [object global], which
is a object and not a function

很明显apply函数没有绑定到push,这导致我尝试这个:

var pushAll = Function.prototype.apply.bind(Array.prototype.push);
pushAll(destination, [6,7]);
console.log(destination); // [1,2,3,4,5,6,7,8]

这显然很好用。我的问题是,为什么我必须绑定push方法才能应用?不应该绑定Array.prototype.push.apply吗?为什么以不同的名称调用它会导致在未绑定的上下文中调用它?

1 个答案:

答案 0 :(得分:5)

  

为什么我必须绑定push方法才能应用?

反过来说:你必须将apply方法绑定到Array push函数 - 你也可以将它绑定到其他函数!否则apply不知道应用参数的方法。

Function.prototype.apply.bind(Array.prototype.push);确实在bind函数上调用apply函数push作为参数,参数 on 然后绑定apply。调用后,生成的函数pushAll将在apply函数上调用push ,并将其参数(数组和参数数组)传递给它。

  

不应该绑定Array.prototype.push.apply吗?

不。 JavaScript被设计为在函数调用时绑定上下文,当它被称为属性时尚未绑定 - 对属性访问没有隐式绑定。否则Array.prototype.push已经绑定到Array.prototype,然后你可以调用任何函数方法,比如bind / apply,并尝试在不同的上下文中使用它。

  

为什么以不同的名称调用它会导致在未绑定的上下文中调用它?

这不是一个不同的名字,而是不同的风格。 (未绑定)函数确实将this值设置为对象,当它们被称为作为方法时,即当对被调用函数的引用是属性访问时:{{1 }}

这允许很大的灵活性,你可以从一个对象“借用”函数并在其他对象上调用它们,仍然是相同的(未绑定)函数。在函数对象不是第一类对象的语言中,这是不可能的。

如果函数(即使它们是方法)被称为普通函数(destination.push()),它们的pushAll()值将为this(除非在草率模式下)。详细了解MDN的this keyword