2017-03-01 43 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), []);