Assume, for the sake of this question, that I want to be able to create a function in Javascript that appends all of the elements of one array to another array. One way to achieve this, if you have access to the destination array, is to say:
假设,为了这个问题,我希望能够在Javascript中创建一个函数,将一个数组的所有元素附加到另一个数组。实现此目的的一种方法是,如果您有权访问目标数组,那就说:
var destination = [1,2,3];
var source = [4,5];
Array.prototype.push.apply(destination, source);
console.log(destination); // [1,2,3,4,5]
Now, since Array.prototype.push.apply is pretty ugly, I want to alias it to something nicer, like:
现在,由于Array.prototype.push.apply非常难看,我想将它别名为更好的东西,例如:
var pushAll = Array.prototype.push.apply;
Which I should be able to call with two arguments, the context (destination) and an array of arguments (source). However, when I try to use the alias, this happens:
我应该能够使用两个参数调用,上下文(目标)和参数数组(源)。但是,当我尝试使用别名时,会发生以下情况:
pushAll(destination, [6,7]);
TypeError: Function.prototype.apply was called on [object global], which
is a object and not a function
So clearly the apply
function is not bound to push
, which led me to try this:
很明显apply函数不一定会推送,这让我尝试这个:
var pushAll = Function.prototype.apply.bind(Array.prototype.push);
pushAll(destination, [6,7]);
console.log(destination); // [1,2,3,4,5,6,7,8]
Which clearly works fine. My question is, why do I have to bind the push method to apply? Shouldn't Array.prototype.push.apply already be bound to apply? Why does calling it under a different name result in calling it on an unbound context?
这显然很好。我的问题是,为什么我必须绑定push方法才能应用?不应该绑定Array.prototype.push.apply应用?为什么以不同的名称调用它会导致在未绑定的上下文中调用它?
1 个解决方案
#1
4
why do I have to bind the push method to apply?
为什么我必须绑定push方法才能应用?
It's the other way round: You have to bind the apply method to the Array push function - you can bind it to other functions as well! Otherwise apply
doesn't know which method to apply with the arguments.
反过来说:你必须将apply方法绑定到Array推送功能 - 你也可以将它绑定到其他功能!否则apply不知道哪个方法适用于参数。
Function.prototype.apply.bind(Array.prototype.push);
does call the bind
function on the apply
function with push
as the argument, the argument on which apply
is then bound. The resulting function pushAll
will, when called, invoke apply
on the push
function, and pass it's argument (the array and the arguments array) to it.
Function.prototype.apply.bind(Array.prototype.push);使用push作为参数调用apply函数上的bind函数,然后绑定应用的参数。结果函数pushAll将在调用时调用push函数,并将其参数(数组和参数数组)传递给它。
Shouldn't Array.prototype.push.apply already be bound to apply?
不应该绑定Array.prototype.push.apply应用?
Nope. JavaScript is designed to bind the context at the call of a function, not already when it's being referred to as a property - there is no implicit binding on property access. Otherwise Array.prototype.push
would already be bound to Array.prototype
, before you could call any Function methods like bind/apply on it and try to use it with a different context.
不。 JavaScript被设计为在函数调用时绑定上下文,当它被称为属性时尚未绑定 - 在属性访问上没有隐式绑定。否则Array.prototype.push已经绑定到Array.prototype,然后你可以调用任何Function方法,比如bind / apply,并尝试将它与不同的上下文一起使用。
Why does calling it under a different name result in calling it on an unbound context?
为什么以不同的名称调用它会导致在未绑定的上下文中调用它?
It's not so much different name, but different style. (Unbound) Functions do get their this
value set to the object when they are called as a method on it, i.e. when the reference to the called function is a property access: destination.push()
.
这不是一个不同的名字,而是不同的风格。 (未绑定)函数在将对象作为方法调用时将其值设置为对象,即当对被调用函数的引用是属性访问时:destination.push()。
This allows for great flexibility, you can "borrow" functions from an object and call them on other objects, still being the same (unbound) function. This is rather impossible in languages where function objects are no first-class objects.
这允许很大的灵活性,您可以从对象“借用”函数并在其他对象上调用它们,仍然是相同的(未绑定)函数。在函数对象不是第一类对象的语言中,这是不可能的。
If functions (even though they were meant to be methods) are called as plain functions (pushAll()
), their this
value will be undefined
(unless in sloppy mode). Read more on the this
keyword at MDN.
如果函数(即使它们是作为方法)被称为普通函数(pushAll()),它们的这个值将是未定义的(除非在草率模式下)。在MDN上阅读有关此关键字的更多信息。
#1
4
why do I have to bind the push method to apply?
为什么我必须绑定push方法才能应用?
It's the other way round: You have to bind the apply method to the Array push function - you can bind it to other functions as well! Otherwise apply
doesn't know which method to apply with the arguments.
反过来说:你必须将apply方法绑定到Array推送功能 - 你也可以将它绑定到其他功能!否则apply不知道哪个方法适用于参数。
Function.prototype.apply.bind(Array.prototype.push);
does call the bind
function on the apply
function with push
as the argument, the argument on which apply
is then bound. The resulting function pushAll
will, when called, invoke apply
on the push
function, and pass it's argument (the array and the arguments array) to it.
Function.prototype.apply.bind(Array.prototype.push);使用push作为参数调用apply函数上的bind函数,然后绑定应用的参数。结果函数pushAll将在调用时调用push函数,并将其参数(数组和参数数组)传递给它。
Shouldn't Array.prototype.push.apply already be bound to apply?
不应该绑定Array.prototype.push.apply应用?
Nope. JavaScript is designed to bind the context at the call of a function, not already when it's being referred to as a property - there is no implicit binding on property access. Otherwise Array.prototype.push
would already be bound to Array.prototype
, before you could call any Function methods like bind/apply on it and try to use it with a different context.
不。 JavaScript被设计为在函数调用时绑定上下文,当它被称为属性时尚未绑定 - 在属性访问上没有隐式绑定。否则Array.prototype.push已经绑定到Array.prototype,然后你可以调用任何Function方法,比如bind / apply,并尝试将它与不同的上下文一起使用。
Why does calling it under a different name result in calling it on an unbound context?
为什么以不同的名称调用它会导致在未绑定的上下文中调用它?
It's not so much different name, but different style. (Unbound) Functions do get their this
value set to the object when they are called as a method on it, i.e. when the reference to the called function is a property access: destination.push()
.
这不是一个不同的名字,而是不同的风格。 (未绑定)函数在将对象作为方法调用时将其值设置为对象,即当对被调用函数的引用是属性访问时:destination.push()。
This allows for great flexibility, you can "borrow" functions from an object and call them on other objects, still being the same (unbound) function. This is rather impossible in languages where function objects are no first-class objects.
这允许很大的灵活性,您可以从对象“借用”函数并在其他对象上调用它们,仍然是相同的(未绑定)函数。在函数对象不是第一类对象的语言中,这是不可能的。
If functions (even though they were meant to be methods) are called as plain functions (pushAll()
), their this
value will be undefined
(unless in sloppy mode). Read more on the this
keyword at MDN.
如果函数(即使它们是作为方法)被称为普通函数(pushAll()),它们的这个值将是未定义的(除非在草率模式下)。在MDN上阅读有关此关键字的更多信息。