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

时间:2017-03-01 20:16:36

标签: javascript arrays node.js prototype higher-order-functions

我正在尝试使用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.concatundefined。这是为什么?

2 个答案:

答案 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), []);