| [ Web Proxy ] |
| Viewing: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce | [Back] [Original] |
Get to know MDN better
Dieser Inhalt wurde automatisch aus dem Englischen bersetzt, und kann Fehler enthalten. Erfahre mehr ber dieses Experiment.
Diese Funktion ist gut etabliert und funktioniert auf vielen Gerten und in vielen Browserversionen. Sie ist seit Juli 2015 browserbergreifend verfgbar.
Die reduce() Methode von Array Instanzen fhrt eine vom Benutzer bereitgestellte "Reducer"-Callback-Funktion fr jedes Element des Arrays in Reihenfolge aus und bergibt den Rckgabewert der vorhergehenden Berechnung. Das Endergebnis des Ausfhrens des Reducers ber alle Elemente des Arrays ist ein einzelner Wert.
Bei der ersten Ausfhrung des Callbacks gibt es keinen "Rckgabewert der vorhergehenden Berechnung". Falls angegeben, kann ein Anfangswert stattdessen verwendet werden. Andernfalls wird das Array-Element an Index 0 als Anfangswert verwendet und die Iteration beginnt beim nchsten Element (Index 1 statt Index 0).
const array = [1, 2, 3, 4];
// 0 + 1 + 2 + 3 + 4
const initialValue = 0;
const sumWithInitial = array.reduce(
(accumulator, currentValue) => accumulator + currentValue,
initialValue,
);
console.log(sumWithInitial);
// Expected output: 10
reduce(callbackFn)
reduce(callbackFn, initialValue)
callbackFnEine Funktion, die fr jedes Element im Array ausgefhrt wird. Ihr Rckgabewert wird zum Wert des accumulator-Parameters beim nchsten Aufruf von callbackFn. Beim letzten Aufruf wird der Rckgabewert zum Rckgabewert von reduce(). Die Funktion wird mit den folgenden Argumenten aufgerufen:
accumulatorDer Wert, der aus dem vorhergehenden Aufruf von callbackFn resultiert. Beim ersten Aufruf ist sein Wert initialValue, falls letzterer angegeben ist; andernfalls ist sein Wert array[0].
currentValueDer Wert des aktuellen Elements. Beim ersten Aufruf ist sein Wert array[0], wenn initialValue angegeben ist; andernfalls ist sein Wert array[1].
currentIndexDie Indexposition von currentValue im Array. Beim ersten Aufruf ist sein Wert 0, wenn initialValue angegeben ist, andernfalls 1.
arrayDas Array, auf dem reduce() aufgerufen wurde.
initialValue OptionalEin Wert, mit dem accumulator beim ersten Aufruf des Callbacks initialisiert wird.
Falls initialValue angegeben ist, beginnt callbackFn mit dem ersten Wert im Array als currentValue.
Falls initialValue nicht angegeben ist, wird accumulator mit dem ersten Wert im Array initialisiert, und callbackFn beginnt mit dem zweiten Wert im Array als currentValue. In diesem Fall, wenn das Array leer ist (sodass es keinen ersten Wert gibt, der als accumulator zurckgegeben werden knnte), wird ein Fehler ausgelst.
Der Wert, der aus dem vollstndigen Ausfhren der "Reducer"-Callback-Funktion ber das gesamte Array resultiert.
TypeErrorWird ausgelst, wenn das Array keine Elemente enthlt und initialValue nicht angegeben ist.
Die reduce() Methode ist eine iterative Methode. Sie fhrt eine "Reducer"-Callback-Funktion ber alle Elemente des Arrays in aufsteigender Indexreihenfolge aus und akkumuliert sie zu einem einzigen Wert. Jedes Mal wird der Rckgabewert von callbackFn beim nchsten Aufruf erneut in callbackFn als accumulator bergeben. Der endgltige Wert von accumulator (der der von callbackFn bei der letzten Iteration ber das Array zurckgegebene Wert ist) wird der Rckgabewert von reduce(). Lesen Sie den Abschnitt ber iterative Methoden fr weitere Informationen darber, wie diese Methoden allgemein funktionieren.
callbackFn wird nur fr Array-Indizes aufgerufen, denen Werte zugewiesen wurden. Es wird nicht fr leere Stellen in dnn besiedelten Arrays aufgerufen.
Im Gegensatz zu anderen iterativen Methoden akzeptiert reduce() kein thisArg Argument. callbackFn wird immer mit undefined als this aufgerufen, das durch globalThis ersetzt wird, falls callbackFn nicht strikt ist.
reduce() ist ein zentrales Konzept in der funktionalen Programmierung, wo es nicht mglich ist, einen Wert zu verndern. Um die Werte in einem Array zu akkumulieren, muss man daher bei jeder Iteration einen neuen Akkumulator-Wert zurckgeben. Diese Konvention setzt sich in JavaScripts reduce() fort: Sie sollten Spread-Syntax oder andere Kopiermethoden verwenden, um neue Arrays und Objekte als Akkumulator zu erstellen, anstatt das bestehende zu verndern. Wenn Sie sich entscheiden, den Akkumulator anstatt zu kopieren zu manipulieren, erinnern Sie sich daran, dennoch das modifizierte Objekt im Callback zurckzugeben, oder die nchste Iteration erhlt undefined. Beachten Sie jedoch, dass das Kopieren des Akkumulators zu erhhtem Speicherverbrauch und verschlechterter Leistung fhren kann sehen Sie Wann man reduce() nicht verwenden sollte fr mehr Details. In solchen Fllen ist es besser, eine for-Schleife zu verwenden, um schlechte Leistung und unverstndlichen Code zu vermeiden.
Die reduce() Methode ist generisch. Sie erwartet nur, dass der this-Wert eine length-Eigenschaft und integer-indizierte Eigenschaften hat.
Hat das Array nur ein Element (unabhngig von der Position) und es wird kein initialValue bereitgestellt, oder wenn initialValue bereitgestellt wird, das Array aber leer ist, wird der Einzelwert ohne Aufruf von callbackFn zurckgegeben.
Wird initialValue bereitgestellt und ist das Array nicht leer, wird die Reduce-Methode die Callback-Funktion immer ab Index 0 aufrufen.
Wird initialValue nicht bereitgestellt, verhlt sich die Reduce-Methode unterschiedlich fr Arrays mit einer Lnge grer als 1, gleich 1 und 0, wie im folgenden Beispiel gezeigt:
const getMax = (a, b) => Math.max(a, b);
// callback is invoked for each element in the array starting at index 0
[1, 100].reduce(getMax, 50); // 100
[50].reduce(getMax, 10); // 50
// callback is invoked once for element at index 1
[1, 100].reduce(getMax); // 100
// callback is not invoked
[50].reduce(getMax); // 50
[].reduce(getMax, 1); // 1
[].reduce(getMax); // TypeError
Der folgende Code zeigt, was passiert, wenn wir reduce() mit einem Array und ohne Anfangswert aufrufen.
const array = [15, 16, 17, 18, 19];
function reducer(accumulator, currentValue, index) {
const returns = accumulator + currentValue;
console.log(
`accumulator: ${accumulator}, currentValue: ${currentValue}, index: ${index}, returns: ${returns}`,
);
return returns;
}
array.reduce(reducer);
Das Callback wrde viermal aufgerufen werden, mit den Argumenten und Rckgabewerten bei jedem Aufruf folgendermaen:
accumulator |
currentValue |
index |
Rckgabewert | |
|---|---|---|---|---|
| Erster Aufruf | 15 |
16 |
1 |
31 |
| Zweiter Aufruf | 31 |
17 |
2 |
48 |
| Dritter Aufruf | 48 |
18 |
3 |
66 |
| Vierter Aufruf | 66 |
19 |
4 |
85 |
Der array Parameter ndert sich whrend des Prozesses nie er ist immer [15, 16, 17, 18, 19]. Der von reduce() zurckgegebene Wert wre der letzte Rckgabewert des letzten Callback-Aufrufs (85).
Hier reduzieren wir dasselbe Array mit demselben Algorithmus, aber mit einem initialValue von 10, der als zweites Argument an reduce() bergeben wird:
[15, 16, 17, 18, 19].reduce(
(accumulator, currentValue) => accumulator + currentValue,
10,
);
Das Callback wrde fnfmal aufgerufen werden, mit den Argumenten und Rckgabewerten bei jedem Aufruf folgendermaen:
accumulator |
currentValue |
index |
Rckgabewert | |
|---|---|---|---|---|
| Erster Aufruf | 10 |
15 |
0 |
25 |
| Zweiter Aufruf | 25 |
16 |
1 |
41 |
| Dritter Aufruf | 41 |
17 |
2 |
58 |
| Vierter Aufruf | 58 |
18 |
3 |
76 |
| Fnfter Aufruf | 76 |
19 |
4 |
95 |
Der von reduce() zurckgegebene Wert in diesem Fall wre 95.
Um die in einem Array von Objekten enthaltenen Werte zu summieren, mssen Sie einen initialValue angeben, damit jedes Element Ihre Funktion durchluft.
const objects = [{ x: 1 }, { x: 2 }, { x: 3 }];
const sum = objects.reduce(
(accumulator, currentValue) => accumulator + currentValue.x,
0,
);
console.log(sum); // 6
Die pipe-Funktion nimmt eine Abfolge von Funktionen und gibt eine neue Funktion zurck. Wenn die neue Funktion mit einem Argument aufgerufen wird, werden die Funktionen in Reihenfolge aufgerufen, wobei jede den Rckgabewert der vorherigen Funktion erhlt.
const pipe =
(...functions) =>
(initialValue) =>
functions.reduce((acc, fn) => fn(acc), initialValue);
// Building blocks to use for composition
const double = (x) => 2 * x;
const triple = (x) => 3 * x;
const quadruple = (x) => 4 * x;
// Composed functions for multiplication of specific values
const multiply6 = pipe(double, triple);
const multiply9 = pipe(triple, triple);
const multiply16 = pipe(quadruple, quadruple);
const multiply24 = pipe(double, triple, quadruple);
// Usage
multiply6(6); // 36
multiply9(9); // 81
multiply16(16); // 256
multiply24(10); // 240
Promise-Sequenzierung ist im Wesentlichen das in dem vorherigen Abschnitt demonstrierte Funktional-Piping, das jedoch asynchron ausgefhrt wird.
// Compare this with pipe: fn(acc) is changed to acc.then(fn),
// and initialValue is ensured to be a promise
const asyncPipe =
(...functions) =>
(initialValue) =>
functions.reduce((acc, fn) => acc.then(fn), Promise.resolve(initialValue));
// Building blocks to use for composition
const p1 = async (a) => a * 5;
const p2 = async (a) => a * 2;
// The composed functions can also return non-promises, because the values are
// all eventually wrapped in promises
const f3 = (a) => a * 3;
const p4 = async (a) => a * 4;
asyncPipe(p1, p2, f3, p4)(10).then(console.log); // 1200
asyncPipe kann auch mit async/await implementiert werden, was seine hnlichkeit mit pipe besser demonstriert:
const asyncPipe =
(...functions) =>
(initialValue) =>
functions.reduce(async (acc, fn) => fn(await acc), initialValue);
reduce() berspringt fehlende Elemente in dnn besiedelten Arrays, aber es berspringt keine undefined Werte.
console.log([1, 2, , 4].reduce((a, b) => a + b)); // 7
console.log([1, 2, undefined, 4].reduce((a, b) => a + b)); // NaN
Die reduce() Methode liest die length-Eigenschaft von this und greift dann auf jede Eigenschaft zu, deren Schlssel eine nicht-negative Ganzzahl kleiner als length ist.
const arrayLike = {
length: 3,
0: 2,
1: 3,
2: 4,
3: 99, // ignored by reduce() since length is 3
};
console.log(Array.prototype.reduce.call(arrayLike, (x, y) => x + y));
// 9
Allzweck-Higher-Order-Funktionen wie reduce() knnen mchtig, aber manchmal schwer zu verstehen sein, besonders fr weniger erfahrene JavaScript-Entwickler. Wenn der Code bei der Verwendung anderer Array-Methoden klarer wird, mssen Entwickler den Lesbarkeitskompromiss gegen die anderen Vorteile der Verwendung von reduce() abwgen.
Beachten Sie, dass reduce() immer gleichwertig zu einer for...of-Schleife ist, auer dass anstatt einer Variable im oberen Gltigkeitsbereich zu ndern, nun bei jeder Iteration der neue Wert zurckgegeben wird:
const val = array.reduce((acc, cur) => update(acc, cur), initialValue);
// Is equivalent to:
let val = initialValue;
for (const cur of array) {
val = update(val, cur);
}
Wie bereits erwhnt, kann es sein, dass Leute reduce() verwenden mchten, um funktionale Programmierungspraktiken von unvernderlichen Daten nachzuahmen. Entwickler, die die Unvernderlichkeit des Akkumulators aufrechterhalten, kopieren daher oft den gesamten Akkumulator bei jeder Iteration, wie folgt:
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = names.reduce((allNames, name) => {
const currCount = Object.hasOwn(allNames, name) ? allNames[name] : 0;
return {
...allNames,
[name]: currCount + 1,
};
}, {});
Dieser Code ist leistungsschwach, da jede Iteration das gesamte allNames-Objekt kopieren muss, das abhngig von der Anzahl der eindeutigen Namen gro sein knnte. Dieser Code hat eine Worst-Case-Performance von O(N^2), wobei N die Lnge von names ist.
Eine bessere Alternative ist es, das allNames-Objekt bei jeder Iteration zu verndern. Wenn allNames jedoch sowieso verndert wird, sollten Sie reduce() in eine for-Schleife umwandeln, was viel klarer ist:
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = names.reduce((allNames, name) => {
const currCount = allNames[name] ?? 0;
allNames[name] = currCount + 1;
// return allNames, otherwise the next iteration receives undefined
return allNames;
}, Object.create(null));
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = Object.create(null);
for (const name of names) {
const currCount = countedNames[name] ?? 0;
countedNames[name] = currCount + 1;
}
Wenn Ihr Akkumulator also ein Array oder Objekt ist und Sie das Array oder Objekt bei jeder Iteration kopieren, knnen Sie versehentlich quadratische Komplexitt in Ihren Code einfhren, was zu einer schnellen Verschlechterung der Leistung bei groen Datenmengen fhrt. Dies ist im realen Code passiert siehe zum Beispiel Making Tanstack Table 1000x faster with a 1 line change.
Einige der akzeptablen Anwendungsflle von reduce() sind oben gegeben (insbesondere, das Summieren eines Arrays, Promise-Sequenzierung und Funktion-Piping). Es gibt andere Flle, in denen es bessere Alternativen zu reduce() gibt.
Flachlegen eines Arrays von Arrays. Verwenden Sie flat() stattdessen.
const flattened = array.reduce((acc, cur) => acc.concat(cur), []);
const flattened = array.flat();
Gruppieren von Objekten nach einer Eigenschaft. Verwenden Sie Object.groupBy() stattdessen.
const groups = array.reduce((acc, obj) => {
const key = obj.name;
const curGroup = acc[key] ?? [];
return { ...acc, [key]: [...curGroup, obj] };
}, {});
const groups = Object.groupBy(array, (obj) => obj.name);
Zusammenfgen von Arrays, die in einem Array von Objekten enthalten sind. Verwenden Sie flatMap() stattdessen.
const friends = [
{ name: "Anna", books: ["Bible", "Harry Potter"] },
{ name: "Bob", books: ["War and peace", "Romeo and Juliet"] },
{ name: "Alice", books: ["The Lord of the Rings", "The Shining"] },
];
const allBooks = friends.reduce((acc, cur) => [...acc, ...cur.books], []);
const allBooks = friends.flatMap((person) => person.books);
Entfernen von Duplikaten in einem Array. Verwenden Sie Set und Array.from() stattdessen.
const uniqArray = array.reduce(
(acc, cur) => (acc.includes(cur) ? acc : [...acc, cur]),
[],
);
const uniqArray = Array.from(new Set(array));
Eliminieren oder Hinzufgen von Elementen in einem Array. Verwenden Sie flatMap() stattdessen.
// Takes an array of numbers and splits perfect squares into its square roots
const roots = array.reduce((acc, cur) => {
if (cur < 0) return acc;
const root = Math.sqrt(cur);
if (Number.isInteger(root)) return [...acc, root, root];
return [...acc, cur];
}, []);
const roots = array.flatMap((val) => {
if (val < 0) return [];
const root = Math.sqrt(val);
if (Number.isInteger(root)) return [root, root];
return [val];
});
Wenn Sie nur Elemente aus einem Array eliminieren, knnen Sie auch filter() verwenden.
Suchen nach Elementen oder Testen, ob Elemente eine Bedingung erfllen. Verwenden Sie find() und findIndex(), oder some() und every() stattdessen. Diese Methoden haben den zustzlichen Vorteil, dass sie zurckgeben, sobald das Ergebnis sicher ist, ohne das komplette Array zu durchlaufen.
const allEven = array.reduce((acc, cur) => acc && cur % 2 === 0, true);
const allEven = array.every((val) => val % 2 === 0);
In Fllen, in denen reduce() die beste Wahl ist, knnen Dokumentationen und semantische Variablennamen helfen, Lesbarkeitsnachteile zu minimieren.
| Spezifikation |
|---|
| ECMAScript 2027 LanguageSpecification # sec-array.prototype.reduce |
Array.prototype.reduce in core-jsArray.prototype.reduceArrayArray.prototype.map()Array.prototype.flat()Array.prototype.flatMap()Array.prototype.reduceRight()TypedArray.prototype.reduce()Object.groupBy()Map.groupBy()Arrayat()concat()copyWithin()entries()every()fill()filter()find()findIndex()findLast()findLastIndex()flat()flatMap()forEach()includes()indexOf()join()keys()lastIndexOf()map()pop()push()reduce()reduceRight()reverse()shift()slice()some()sort()splice()toLocaleString()toReversed()toSorted()toSpliced()toString()unshift()values()with()[Symbol.iterator]()Object/FunctionDer Bauplan fr ein besseres Internet.
Teile dieses Inhalts sind 19982026 von einzelnen mozilla.org-Mitwirkenden. Inhalte sind verfgbar unter einer Creative-Commons-Lizenz.
| Web Proxy Viewer | New URL | Original Page |