我正在尝试使用reduce连接一个数组数组,我想我可以像这样使用Array.prototype.concat函数:
arr = [[1],[2],[3]]
arr.reduce((a, b) => Array.prototype.concat(a, b), [])
哪个工作正常,并给我数组[1, 2, 3]
。然后我觉得我可以更聪明,就这样做:
arr = [[1],[2],[3]]
arr.reduce(Array.prototype.concat, [])
然而,这给了我一个错误:
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)
似乎认为Array.prototype.concat
是undefined
。这是为什么?
答案 0 :(得分:3)
concat
作为关于某个对象的方法(即方法执行的this
值)运行。将函数传递给函数时,不会传递任何this
值。因此,你有效地做了类似的事情:
var rawConcat = Array.prototype.concat;
rawConcat(a,b);
您可以使用bind
创建一个功能的副本,其中包含特定的this
:
arr.reduce(Array.prototype.concat.bind(Array.prototype), [])
然而,现在已经解决了这个问题,还有其他几个问题阻止你这样做。
首先,reduce
实际上得到四个参数,包括当前索引和整个数组。您可以通过让(a,b)=>
lambda仅将这四个参数中的两个传递到concat
来忽略这些。这很好,但是当你直接提供函数作为reduce
的参数时,它将使用所有四个参数,因此你将得到调用Array.prototype.concat(a, b, currentIndex, arr)
的结果。
此外,你正在做的事情不是Array.prototype
的合理使用。 concat
函数连接其参数并将它们附加到this
值的副本。由于Array.prototype
本身只是一个空数组(尽管有许多其他数组用作继承属性的自有属性),这实际上与[].concat(a,b)
或(可能更可读){{1}相同}。
答案 1 :(得分:0)
Array.prototype.concat
期望上下文(this
)是一个数组,在你的第一个例子中,上下文实际上是Array.prototype
,它偶然看起来像一个数组,因此它可以工作。
然而,您的第二个示例通过引用传递concat函数,因此上下文为null或未定义。
更正确的方法是使用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), []);