为什么应用程序尚未绑定到Javascript中的函数?
为了回答这个问题,假设我希望能够在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非
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))代码>