为什么我们不能直接将Array.prototype.concat提供给reduce?

时间:2017-02-17 05:20:01

标签: javascript

JavaScript新手在这里。今天我学会了reduce并开始实现我自己的数组展平功能。

我拥有的是

var array = [[1, 2], [3, 4, 5], [6]];
var result = array.reduce(Array.prototype.concat, []); // Causes Uncaught TypeError: Array.prototype.concat called on null or undefined
var result = array.reduce(Array.prototype.concat.call, []); // Causes Uncaught TypeError: undefined is not a function

虽然Merge/flatten an array of arrays in JavaScript?中的答案是优雅和惯用的,但我真的很感激我的尝试失败的例证。

3 个答案:

答案 0 :(得分:4)

您的代码等同于

result = array.reduce(fn, []);
function fn(a, b, index, array) { // this is the arguments reduce sends to the callback
    return Array.prototype.concat.call(null, a, b, index, array);
}
你能发现问题吗?

答案 1 :(得分:2)

您对Array.prototype.concat.call有正确的想法。使用Array.prototype.concat,调用将如下所示:

var concat = Array.prototype.concat;

concat(concat(concat([],
                     [1, 2]),
              [3, 4, 5]),
       [6])

不起作用,因为Array.prototype.concat将其参数连接到this;将其称为concat()会为this提供undefinedcall怎么样?

var call = Array.prototype.concat.call;

call(call(call([],
               [1, 2]),
          [3, 4, 5]),
     [6])

这会遇到同样的问题,但使用Function.prototype.callArray.prototype.concat是一个与其他函数类似的函数,并从call继承其Function.prototype方法。 call尝试调用this,但将其称为call()会为this提供undefined

您可以传递Function.prototype.call.bind(Array.prototype.concat) ...如果reduce没有使用更多参数调用其函数,而不仅仅是累加器和当前项。但它确实传递了当前项目和上下文数组的索引,并且通过仅传递包含一些内置函数的Array.prototype.concat来破坏任何实现此工作的机会。

答案 2 :(得分:0)

这是因为Array.prototype.concat需要一个函数原型,这样它就是一个数组或值列表,可以连接到主数组。

但是,回复Array.prototype.reduce需要accumulatorcurrentValuecurrentIndexarray作为参数。

参数(以及他们应该做的事情)不匹配,因此会出现意外结果或错误。