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

Using prototype functions in higher order functions in javascript

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

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

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) 或(可能更易读)a.concat(b).