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

Sta*_*ank 5 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]
Run Code Online (Sandbox Code Playgroud)

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

var pushAll = Array.prototype.push.apply;
Run Code Online (Sandbox Code Playgroud)

我应该能够使用两个参数调用,上下文(目标)和参数数组(源).但是,当我尝试使用别名时,会发生以下情况:

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

所以很明显这个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]
Run Code Online (Sandbox Code Playgroud)

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

Ber*_*rgi 5

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

反过来说:你必须将apply方法绑定到Array推送功能 - 你也可以将它绑定到其他功能!否则apply不知道哪个方法适用于参数.

Function.prototype.apply.bind(Array.prototype.push);不调用bind功能apply功能与push作为参数,该参数关于哪个apply然后约束.将得到的功能pushAll将被调用时,调用apply push功能,和它的参数(该阵列和参数的数组)传递给它.

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

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

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

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

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

如果函数(即使它们被认为是方法)被称为普通函数(pushAll()),它们的this值将是undefined(除非在草率模式下).在MDN 上阅读this关键字的更多信息.