[英]Using prototype functions in higher order functions in javascript
I'm trying to concat an array of arrays using reduce and I figured that I could use the Array.prototype.concat function like this: 我正在尝试使用reduce来连接一个数组数组,我想我可以像这样使用Array.prototype.concat函数:
arr = [[1],[2],[3]]
arr.reduce((a, b) => Array.prototype.concat(a, b), [])
Which works fine and gives me the array [1, 2, 3]
. 哪个工作正常,并给我阵列
[1, 2, 3]
。 Then I thought I could be even smarter and do it like this: 然后我想我可以变得更聪明,并且这样做:
arr = [[1],[2],[3]]
arr.reduce(Array.prototype.concat, [])
This however gives me an error: 但是这给了我一个错误:
TypeError: Array.prototype.concat called on null or undefined
at Array.reduce (native)
at Object.<anonymous> (/home/axel/Developer/temp/reduce2.js:2:5)
at Module._compile (module.js:556:32)
at Object.Module._extensions..js (module.js:565:10)
at Module.load (module.js:473:32)
at tryModuleLoad (module.js:432:12)
at Function.Module._load (module.js:424:3)
at Module.runMain (module.js:590:10)
at run (bootstrap_node.js:394:7)
at startup (bootstrap_node.js:149:9)
It seems to think that Array.prototype.concat
is undefined
. 似乎认为
Array.prototype.concat
undefined
。 Why is this? 为什么是这样?
concat
operates as a method with respect to some object (ie, the this
value of the method's execution). concat
作为一个关于某个对象的方法(即方法执行的this
值)运行。 When you pass a function into a function, you do not pass along any this
value. 将函数传递给函数时,不传递任何
this
值。 Thus, you're effectively doing something similar to: 因此,你有效地做了类似的事情:
var rawConcat = Array.prototype.concat;
rawConcat(a,b);
You can use bind
to create a copy of a function with a particular this
burned into it: 你可以使用
bind
来创建一个函数的副本,其中特定的this
被烧入其中:
arr.reduce(Array.prototype.concat.bind(Array.prototype), [])
However, now that that's cleared up, there are several other issues that stop you from doing this. 但是,现在已经解决了,还有其他几个问题阻止你这样做。
For one, reduce
actually gets four arguments, including the current index and the whole array. 首先,
reduce
实际上有四个参数,包括当前索引和整个数组。 You ignore these by having your (a,b)=>
lambda only pass two of those four arguments into concat
. 你通过让你的
(a,b)=>
lambda只将这四个参数中的两个传递给concat
忽略这些。 That's fine, but when you supply a function directly as an argument to reduce
, it will use all four arguments, so you'll get the result of the call Array.prototype.concat(a, b, currentIndex, arr)
. 这很好,但是当你直接提供一个函数作为
reduce
的参数时,它将使用所有四个参数,因此你将获得调用Array.prototype.concat(a, b, currentIndex, arr)
。
Furthermore, what you're doing isn't a sensible use of Array.prototype
. 此外,您正在做的不是合理使用
Array.prototype
。 The concat
function concatenates its arguments and appends them to a copy of the this
value. concat
函数连接其参数并将它们附加this
值的副本。 Since Array.prototype
is itself just an empty array (albeit with many own-properties that other arrays use as inherited properties), this is effectively the same as [].concat(a,b)
or (perhaps even more readably) a.concat(b)
. 由于
Array.prototype
本身只是一个空数组(尽管有许多其他数组用作继承属性的自有属性),这实际上与[].concat(a,b)
或(甚至更可读) a.concat(b)
。
Array.prototype.concat
expects the context ( this
) to be an Array and in your first example the context is actually Array.prototype
which incidentally looks exactly like an Array, hence it works. Array.prototype.concat
期望上下文( this
)是一个数组,在你的第一个例子中,上下文实际上是Array.prototype
,它偶然看起来像一个数组,因此它可以工作。
Your second example however, passes the concat function by reference so the context is null or undefined. 但是,您的第二个示例通过引用传递concat函数,因此上下文为null或未定义。
The more correct way to do this would be to use Function.prototype.call
to bind the context to one of the arrays or call the method directly on the array, eg 更正确的方法是使用
Function.prototype.call
将上下文绑定到其中一个数组或直接在数组上调用方法,例如
arr = [[1],[2],[3]];
arr.reduce((a, b) => Array.prototype.concat.call(a, b), []);
// Or
arr.reduce((a, b) => a.concat(b), []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.