2017-03-01 16 views
1

我试图使用Concat的减少数组的数组,我想,我可以使用Array.prototype.concat功能是这样的:使用原型功能高阶函数在JavaScript

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。为什么是这样?

+0

您必须将参数传递到'reduce'函数,并将其转换为'concat'并返回一些内容,因为此时您的'reduce'函数不返回任何内容。 –

+1

请注意,您的初始代码中的第二行应该实际读取'arr = arr.reduce((a,b)=> a.concat(b));'这使得进一步减少成为不可能。 –

+0

@Kinduser该函数确实会返回一些内容。箭头函数只允许单个表达式作为它们的主体,并将该表达式的结果用作它们的返回值。 – apsillers

回答

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.prototypeconcat函数将其参数连接起来并附加到值this的副本中。由于Array.prototype本身就是一个空的数组(尽管有许多其他数组用作继承属性的属性),但它实际上与[].concat(a,b)或(甚至更易读)a.concat(b)相同。

0

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