Signatur
Beschreibung
Iterator.prototype.reduce() gehört zu den Iterator Helpers und arbeitet wie Array.prototype.reduce(), nur direkt auf einem Iterator. Für jedes Element, das der Iterator liefert, wird die Reducer-Funktion aufgerufen. Sie bekommt den bisherigen Akkumulator und den aktuellen Wert und gibt den neuen Akkumulator zurück. Wenn der Iterator erschöpft ist, liefert die Methode den letzten Akkumulator zurück.
Der größte Vorteil: Man muss vorher kein Array bauen, etwa mit [...iterator] oder Array.from(). Das spart Speicher bei großen oder erzeugten Datenfolgen, zum Beispiel bei Generatoren, Map.prototype.entries(), Set.prototype.values() oder Ketten wie iter.filter(...).map(...). Anders als map() oder filter() arbeitet reduce() nicht verzögert: Die Methode verbraucht den Iterator sofort und vollständig.
Ohne initialValue wird das erste Element des Iterators zum Startwert des Akkumulators, und der Callback läuft erst ab dem zweiten Element. Ein leerer Iterator ohne Startwert führt dann zu einem TypeError. Der Callback erhält als dritten Parameter einen fortlaufenden Zähler (counter), aber anders als bei Arrays kein viertes Argument mit der Quelle.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $callbackFn Pflicht | (accumulator: any, currentValue: any, counter: number) => any | Reducer-Funktion, die für jedes Element aufgerufen wird. Ihr Rückgabewert wird beim nächsten Aufruf zu accumulator. counter ist der Index des aktuellen Elements (beginnt bei 0 bzw. bei 1, wenn kein Startwert angegeben ist). |
|
| $initialValue | any | erstes Element des Iterators | Startwert des Akkumulators. Fehlt er, wird das erste Element als Startwert genommen, und der Callback läuft erst ab dem zweiten Element. |
Rückgabewert
Beispiele
Summe über einen Generator ohne Zwischen-Array
function* zahlen(bis) {
for (let i = 1; i <= bis; i++) yield i;
}
const summe = zahlen(100).reduce((acc, n) => acc + n, 0);
console.log(summe);
Warenkorb-Summe aus einer Map mit filter() und map() verketten
const warenkorb = new Map([
['Buch', { preis: 19.9, menge: 2 }],
['Stift', { preis: 1.5, menge: 0 }],
['Heft', { preis: 3.2, menge: 5 }]
]);
const gesamt = warenkorb.values()
.filter(({ menge }) => menge > 0)
.map(({ preis, menge }) => preis * menge)
.reduce((acc, betrag) => acc + betrag, 0);
console.log(gesamt.toFixed(2));
Wörter zählen und in ein Objekt gruppieren
const text = 'rot grün rot blau grün rot';
const woerter = text.split(' ').values();
const haeufigkeit = woerter.reduce((acc, wort) => {
acc[wort] = (acc[wort] ?? 0) + 1;
return acc;
}, {});
console.log(haeufigkeit);
Ohne Startwert: Maximum ermitteln und leeren Iterator abfangen
const max = [4, 17, 9].values().reduce((a, b) => Math.max(a, b));
console.log(max);
try {
[].values().reduce((a, b) => a + b);
} catch (err) {
console.log(err instanceof TypeError);
}
// Wichtig · Fallstricke
- Verbraucht den Iterator: Nach
reduce()ist der Iterator erschöpft und lässt sich nicht erneut durchlaufen. Wer die Daten noch einmal braucht, muss einen neuen Iterator anlegen, etwa durch einen erneuten Aufruf vonmap.values(). - Leerer Iterator ohne Startwert: Das wirft einen
TypeError. Gib deshalb möglichst immer eineninitialValuean. - Unendliche Iteratoren:
reduce()endet nie, wenn der Iterator nie fertig wird. Begrenze die Folge vorher mittake(). - Fehler im Callback: Wirft der Callback eine Ausnahme, schließt die Methode den zugrunde liegenden Iterator über
return()und gibt den Fehler weiter. - Kein viertes Argument: Anders als bei
Array.prototype.reduce()bekommt der Callback nicht die Quelle übergeben. - Kompatibilität: Die Iterator Helpers sind neu (ES2025). Ältere Browser und Node.js-Versionen vor 22 unterstützen sie nicht. Dort helfen ein Polyfill (z. B. core-js) oder
Array.from(iter).reduce(...). - Nur synchron: Asynchrone Iteratoren haben diese Methode nicht. Für sie gibt es nur den Vorschlag Async Iterator Helpers.