在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.concat
是undefined
。 为什么是这样?
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), []);