1

Ich versuche, ein Array von Arrays zu verketten reduzieren verwenden und ich dachte, dass ich die Array.prototype.concat Funktion wie diese verwenden:Mit Prototyp Funktionen in Funktionen höherer Ordnung in Javascript

arr = [[1],[2],[3]] 
arr.reduce((a, b) => Array.prototype.concat(a, b), []) 

Welche funktioniert gut und gibt mir das Array [1, 2, 3]. Dann dachte ich, dass ich noch klüger sein könnte und tun es wie folgt aus:

arr = [[1],[2],[3]] 
arr.reduce(Array.prototype.concat, []) 

Dies jedoch ist mir ein Fehler:

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) 

Es scheint zu denken, dass Array.prototype.concatundefined ist. Warum ist das?

+0

Sie müssen die Argumente sowohl in die 'reduce'-Funktion als auch in 'concat' übergeben und etwas zurückgeben, da Ihre' reduce'-Funktion in diesem Moment nichts zurückgibt. –

+1

Beachten Sie, dass die zweite Zeile in Ihrem ursprünglichen Code tatsächlich lesen sollte: arr = arr.reduce ((a, b) => a.concat (b)); was eine weitere Reduktion unmöglich macht. –

+0

@Kinduser Die Funktion gibt etwas zurück. Pfeilfunktionen erlauben nur einen einzigen Ausdruck als ihren Körper und verwenden das Ergebnis dieses Ausdrucks als ihren Rückgabewert. – apsillers

Antwort

3

concat arbeitet als ein Verfahren mit Bezug auf einen Gegenstand (das heißt der Wert this der Ausführung des Verfahrens). Wenn Sie eine Funktion in eine Funktion übergeben, übergeben Sie keinen Wert this. So tun Sie effektiv etwas Ähnliches wie:

var rawConcat = Array.prototype.concat; 
rawConcat(a,b); 

Sie bind verwenden können, um eine Kopie einer Funktion mit einem bestimmten this hinein verbrannt zu erstellen:

arr.reduce(Array.prototype.concat.bind(Array.prototype), []) 

Doch jetzt, dass das geklärt ist oben, gibt es einige andere Probleme, die dich davon abhalten, dies zu tun.

Zum einen, reduce tatsächlich bekommt vier Argumente, einschließlich der aktuellen Index und das gesamte Array. Sie ignorieren diese, indem Sie Ihr (a,b)=> Lambda nur zwei dieser vier Argumente in concat übergeben. Das ist in Ordnung, aber wenn Sie eine Funktion direkt als Argument an reduce liefern, wird es alle vier Argumente verwenden, so erhalten Sie das Ergebnis des Aufrufs Array.prototype.concat(a, b, currentIndex, arr).

Darüber hinaus ist, was Sie tun, keine sinnvolle Verwendung von Array.prototype. Die concat-Funktion verkettet ihre Argumente und hängt sie an eine Kopie des Werts this an. Da Array.prototype selbst nur ein leeres Array ist (wenn auch mit vielen eigenen Eigenschaften, die andere Arrays als vererbte Eigenschaften verwenden), ist dies effektiv dasselbe wie [].concat(a,b) oder (vielleicht noch lesbarer) a.concat(b).

0

Array.prototype.concat erwartet, dass der Kontext (this) ein Array zu sein und in Ihrem ersten Beispiel ist der Kontext tatsächlich Array.prototype die übrigens genau wie ein Array aussieht, damit es funktioniert.

Ihr zweites Beispiel übergibt jedoch die concat-Funktion als Verweis, sodass der Kontext null oder undefiniert ist.

Der richtigere Weg, dies zu tun wäre, Function.prototype.call zu verwenden, um den Kontext an eines der Arrays zu binden oder die Methode direkt auf dem Array aufzurufen, z.

arr = [[1],[2],[3]]; 
arr.reduce((a, b) => Array.prototype.concat.call(a, b), []); 

// Or 

arr.reduce((a, b) => a.concat(b), []); 
Verwandte Themen