TL;DR, den Anfangswert festlegen
Verwendung von Destrukturierung
arr.reduce( ( sum, { x } ) => sum + x , 0)
Ohne Destrukturierung
arr.reduce( ( sum , cur ) => sum + cur.x , 0)
Mit Typoskript
arr.reduce( ( sum, { x } : { x: number } ) => sum + x , 0)
Versuchen wir es mit der Methode der Destrukturierung:
const arr = [ { x: 1 }, { x: 2 }, { x: 4 } ]
const result = arr.reduce( ( sum, { x } ) => sum + x , 0)
console.log( result ) // 7
Der Schlüssel dazu ist die Festlegung des Anfangswerts. Der Rückgabewert wird zum ersten Parameter der nächsten Iteration.
Die in der oberen Antwort verwendete Technik ist nicht idiomatisch
Die akzeptierte Antwort schlägt vor, den "optionalen" Wert NICHT zu übergeben. Dies ist falsch, da der idiomatische Weg ist, dass der zweite Parameter immer einbezogen werden. Warum? Aus drei Gründen:
1. Gefährlich -- Die Nichtübergabe des Anfangswerts ist gefährlich und kann zu Nebenwirkungen und Mutationen führen, wenn die Callback-Funktion unvorsichtig ist.
Siehe
const badCallback = (a,i) => Object.assign(a,i)
const foo = [ { a: 1 }, { b: 2 }, { c: 3 } ]
const bar = foo.reduce( badCallback ) // bad use of Object.assign
// Look, we've tampered with the original array
foo // [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]
Hätten wir es aber so gemacht, mit dem Ausgangswert:
const bar = foo.reduce( badCallback, {})
// foo is still OK
foo // { a: 1, b: 2, c: 3 }
Für das Protokoll, es sei denn, Sie beabsichtigen, das ursprüngliche Objekt zu verändern, setzen Sie den ersten Parameter von Object.assign
auf ein leeres Objekt. Zum Beispiel so: Object.assign({}, a, b, c)
.
2 - Bessere Typeninferenz -Wenn Sie ein Tool wie Typescript oder einen Editor wie VS Code verwenden, haben Sie den Vorteil, dass Sie dem Compiler den Anfangswert mitteilen und er Fehler erkennen kann, wenn Sie es falsch machen. Wenn Sie den Anfangswert nicht angeben, kann er in vielen Situationen nicht erraten, was zu gruseligen Laufzeitfehlern führen kann.
3 - Respektieren Sie die Funktionsträger -- JavaScript glänzt am besten, wenn sein inneres funktionales Kind entfesselt wird. In der funktionalen Welt gibt es einen Standard, wie Sie "falten" oder reduce
ein Array. Wenn Sie ein Array falten oder anwenden Katamorphismus zum Array hinzufügen, nehmen Sie die Werte dieses Arrays, um einen neuen Typ zu konstruieren. Sie müssen den resultierenden Typ mitteilen - das sollten Sie auch dann tun, wenn der endgültige Typ der der Werte in dem Array, einem anderen Array oder einem anderen Typ entspricht.
Betrachten wir es einmal anders. In JavaScript können Funktionen wie Daten weitergegeben werden, so funktionieren Rückrufe, was ist das Ergebnis des folgenden Codes?
[1,2,3].reduce(callback)
Wird sie eine Zahl zurückgeben? Ein Objekt? Das macht es klarer
[1,2,3].reduce(callback,0)
Lesen Sie hier mehr über die Spezifikation der funktionalen Programmierung: https://github.com/fantasyland/fantasy-land#foldable
Einige weitere Hintergrundinformationen
Les reduce
Methode benötigt zwei Parameter,
Array.prototype.reduce( callback, initialItem )
Les callback
Funktion nimmt folgende Parameter entgegen
(accumulator, itemInArray, indexInArray, entireArray) => { /* do stuff */ }
Für die erste Iteration,
-
Si initialItem
vorgesehen ist, wird die reduce
Funktion übergibt die initialItem
als die accumulator
und das erste Element des Arrays als itemInArray
.
-
Si initialItem
es no vorausgesetzt, die reduce
Funktion übergibt das erste Element im Array als initialItem
und das zweite Element im Array als itemInArray
was ein verwirrendes Verhalten sein kann.
Ich lehre und empfehle, immer den Anfangswert von reduce einzustellen.
Sie können die Dokumentation unter folgender Adresse einsehen:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Ich hoffe, das hilft!