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

为什么应用程序尚未绑定到Javascript中的函数?,javascript,prototype,bind,apply,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非

为了回答这个问题,假设我希望能够在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;
我应该能够用两个参数调用它,上下文(目标)和一个参数数组(源)。但是,当我尝试使用别名时,会发生以下情况:

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不应该绑定到应用吗?为什么用不同的名称调用它会导致在未绑定的上下文中调用它

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


反过来说:您必须将apply方法绑定到Array push函数——您也可以将它绑定到其他函数!否则,
apply
不知道该对参数应用哪个方法

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

Array.prototype.push.apply不应该绑定到应用吗

没有。JavaScript被设计为在函数调用时绑定上下文,而不是在它被称为属性时绑定上下文-在属性访问上没有隐式绑定。否则,
Array.prototype.push
将已绑定到
Array.prototype
,然后才能对其调用任何函数方法,如bind/apply,并尝试将其用于其他上下文

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

它的名字不太一样,但风格不同。(未绑定)函数在作为对象上的方法调用时,即当对被调用函数的引用是属性访问时,会将其
值设置为对象:
destination.push()

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


如果函数(即使它们本来是方法)被称为普通函数(
pushAll()
),则它们的
值将是
未定义的
(除非处于草率模式)。阅读更多关于at MDN的内容。

相反:您必须将
apply
方法绑定到数组
push
函数!看@Bergi我很好奇你的意思。我不熟悉JavaScript和绑定函数的概念。当我说
Function.prototype.apply.bind(Array.prototype.push)
时,我是将
push
绑定到
apply
this
值,还是将
apply
绑定到
push
?但答案很简单,没有隐式绑定。实例之间共享一个方法,并且您正在传递对该方法的引用。如果要对它进行绑定,那么它作为一个通用方法就没有用处了。它无法在飞行中做出决定,因为它不知道它的最终目的是什么。是的,它知道,这是一个小小的改进。fiddle还包括一些您想要的功能,即有一个指向
push
方法的函数(如,
var\u oldPush=Array.prototype.push
),这样您就可以对其使用
调用
应用
\u oldPush.apply(目的地,源代码>)?如果您想要更多的代码示例,只需提及:-)您也可以使用
call
类似的技巧,例如:
['one','liner'].map(Function.prototype.call.bind(String.prototype.trim))