在javascript中使用更高阶函数的原型函数

我试图concat使用减less数组的数组,我想我可以使用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.concatundefined 。 为什么是这样?

concat作为一个对象的方法(即方法执行的this值)。 当你把一个函数传递给一个函数时,你不会传递任何this值。 因此,你有效地做了类似于:

 var rawConcat = Array.prototype.concat; rawConcat(a,b); 

您可以使用bind来创build一个函数的副本,并将其烧入其中:

 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本身就是一个空数组(尽pipe有许多其他数组用作inheritance属性的属性),这与[].concat(a,b)或者(甚至更可读) a.concat(b)

Array.prototype.concat期望上下文( this )是一个数组,在你的第一个例子中,上下文实际上是Array.prototype ,顺便看起来像一个数组,因此它的工作原理。

你的第二个例子,通过引用传递concat函数,所以上下文是空的或未定义的。

更正确的方法是使用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), []);