Movatterモバイル変換


[0]ホーム

URL:


  1. Web
  2. JavaScript
  3. JavaScript-Referenz
  4. Eingebaute Standardobjekte
  5. Array
  6. reduce()

Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.

View in EnglishAlways switch to English

Array.prototype.reduce()

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since ⁨Juli 2015⁩.

Diereduce() Methode vonArray Instanzen führt eine vom Benutzer bereitgestellte "Reducer"-Callback-Funktion für jedes Element des Arrays in Reihenfolge aus und übergibt den Rückgabewert der vorhergehenden Berechnung. Das Endergebnis des Ausführens des Reducers über alle Elemente des Arrays ist ein einzelner Wert.

Bei der ersten Ausführung des Callbacks gibt es keinen "Rückgabewert 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 nächsten Element (Index 1 statt Index 0).

Probieren Sie es aus

const array = [1, 2, 3, 4];// 0 + 1 + 2 + 3 + 4const initialValue = 0;const sumWithInitial = array.reduce(  (accumulator, currentValue) => accumulator + currentValue,  initialValue,);console.log(sumWithInitial);// Expected output: 10

Syntax

js
reduce(callbackFn)reduce(callbackFn, initialValue)

Parameter

callbackFn

Eine Funktion, die für jedes Element im Array ausgeführt wird. Ihr Rückgabewert wird zum Wert desaccumulator-Parameters beim nächsten Aufruf voncallbackFn. Beim letzten Aufruf wird der Rückgabewert zum Rückgabewert vonreduce(). Die Funktion wird mit den folgenden Argumenten aufgerufen:

accumulator

Der Wert, der aus dem vorhergehenden Aufruf voncallbackFn resultiert. Beim ersten Aufruf ist sein WertinitialValue, falls letzterer angegeben ist; andernfalls ist sein Wertarray[0].

currentValue

Der Wert des aktuellen Elements. Beim ersten Aufruf ist sein Wertarray[0], wenninitialValue angegeben ist; andernfalls ist sein Wertarray[1].

currentIndex

Die Indexposition voncurrentValue im Array. Beim ersten Aufruf ist sein Wert0, wenninitialValue angegeben ist, andernfalls1.

array

Das Array, auf demreduce() aufgerufen wurde.

initialValueOptional

Ein Wert, mit demaccumulator beim ersten Aufruf des Callbacks initialisiert wird.FallsinitialValue angegeben ist, beginntcallbackFn mit dem ersten Wert im Array alscurrentValue.FallsinitialValuenicht angegeben ist, wirdaccumulator mit dem ersten Wert im Array initialisiert, undcallbackFn beginnt mit dem zweiten Wert im Array alscurrentValue. In diesem Fall, wenn das Array leer ist (sodass es keinen ersten Wert gibt, der alsaccumulator zurückgegeben werden könnte), wird ein Fehler ausgelöst.

Rückgabewert

Der Wert, der aus dem vollständigen Ausführen der "Reducer"-Callback-Funktion über das gesamte Array resultiert.

Ausnahmen

TypeError

Wird ausgelöst, wenn das Array keine Elemente enthält undinitialValue nicht angegeben ist.

Beschreibung

Diereduce() Methode ist eineiterative Methode. Sie führt eine "Reducer"-Callback-Funktion über alle Elemente des Arrays in aufsteigender Indexreihenfolge aus und akkumuliert sie zu einem einzigen Wert. Jedes Mal wird der Rückgabewert voncallbackFn beim nächsten Aufruf erneut incallbackFn alsaccumulator übergeben. Der endgültige Wert vonaccumulator (der der voncallbackFn bei der letzten Iteration über das Array zurückgegebene Wert ist) wird der Rückgabewert vonreduce(). Lesen Sie den Abschnitt überiterative Methoden für weitere Informationen darüber, wie diese Methoden allgemein funktionieren.

callbackFn wird nur für Array-Indizes aufgerufen, denen Werte zugewiesen wurden. Es wird nicht für leere Stellen indünn besiedelten Arrays aufgerufen.

Im Gegensatz zu andereniterativen Methoden akzeptiertreduce() keinthisArg Argument.callbackFn wird immer mitundefined alsthis aufgerufen, das durchglobalThis ersetzt wird, fallscallbackFn nicht strikt ist.

reduce() ist ein zentrales Konzept in derfunktionalen Programmierung, wo es nicht möglich ist, einen Wert zu verändern. Um die Werte in einem Array zu akkumulieren, muss man daher bei jeder Iteration einen neuen Akkumulator-Wert zurückgeben. Diese Konvention setzt sich in JavaScriptsreduce() fort: Sie solltenSpread-Syntax oder andere Kopiermethoden verwenden, um neue Arrays und Objekte als Akkumulator zu erstellen, anstatt das bestehende zu verändern. Wenn Sie sich entscheiden, den Akkumulator anstatt zu kopieren zu manipulieren, erinnern Sie sich daran, dennoch das modifizierte Objekt im Callback zurückzugeben, oder die nächste Iteration erhältundefined. Beachten Sie jedoch, dass das Kopieren des Akkumulators zu erhöhtem Speicherverbrauch und verschlechterter Leistung führen kann — sehen SieWann man reduce() nicht verwenden sollte für mehr Details. In solchen Fällen ist es besser, einefor-Schleife zu verwenden, um schlechte Leistung und unverständlichen Code zu vermeiden.

Diereduce() Methode istgenerisch. Sie erwartet nur, dass derthis-Wert einelength-Eigenschaft und integer-indizierte Eigenschaften hat.

Randfälle

Hat das Array nur ein Element (unabhängig von der Position) und es wird keininitialValue bereitgestellt, oder wenninitialValue bereitgestellt wird, das Array aber leer ist, wird der Einzelwertohne Aufruf voncallbackFn zurückgegeben.

WirdinitialValue bereitgestellt und ist das Array nicht leer, wird die Reduce-Methode die Callback-Funktion immer ab Index 0 aufrufen.

WirdinitialValue nicht bereitgestellt, verhält sich die Reduce-Methode unterschiedlich für Arrays mit einer Länge größer als 1, gleich 1 und 0, wie im folgenden Beispiel gezeigt:

js
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

Beispiele

Wie reduce() ohne Anfangswert funktioniert

Der folgende Code zeigt, was passiert, wenn wirreduce() mit einem Array und ohne Anfangswert aufrufen.

js
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 würde viermal aufgerufen werden, mit den Argumenten und Rückgabewerten bei jedem Aufruf folgendermaßen:

accumulatorcurrentValueindexRückgabewert
Erster Aufruf1516131
Zweiter Aufruf3117248
Dritter Aufruf4818366
Vierter Aufruf6619485

Derarray Parameter ändert sich während des Prozesses nie – er ist immer[15, 16, 17, 18, 19]. Der vonreduce() zurückgegebene Wert wäre der letzte Rückgabewert des letzten Callback-Aufrufs (85).

Wie reduce() mit einem Anfangswert funktioniert

Hier reduzieren wir dasselbe Array mit demselben Algorithmus, aber mit eineminitialValue von10, der als zweites Argument anreduce() übergeben wird:

js
[15, 16, 17, 18, 19].reduce(  (accumulator, currentValue) => accumulator + currentValue,  10,);

Das Callback würde fünfmal aufgerufen werden, mit den Argumenten und Rückgabewerten bei jedem Aufruf folgendermaßen:

accumulatorcurrentValueindexRückgabewert
Erster Aufruf1015025
Zweiter Aufruf2516141
Dritter Aufruf4117258
Vierter Aufruf5818376
Fünfter Aufruf7619495

Der vonreduce() zurückgegebene Wert in diesem Fall wäre95.

Summe von Werten in einem Objekt-Array

Um die in einem Array von Objekten enthaltenen Werte zu summieren,müssen Sie eineninitialValue angeben, damit jedes Element Ihre Funktion durchläuft.

js
const objects = [{ x: 1 }, { x: 2 }, { x: 3 }];const sum = objects.reduce(  (accumulator, currentValue) => accumulator + currentValue.x,  0,);console.log(sum); // 6

Funktional sequentielles Piping

Diepipe-Funktion nimmt eine Abfolge von Funktionen und gibt eine neue Funktion zurück. Wenn die neue Funktion mit einem Argument aufgerufen wird, werden die Funktionen in Reihenfolge aufgerufen, wobei jede den Rückgabewert der vorherigen Funktion erhält.

js
const pipe =  (...functions) =>  (initialValue) =>    functions.reduce((acc, fn) => fn(acc), initialValue);// Building blocks to use for compositionconst double = (x) => 2 * x;const triple = (x) => 3 * x;const quadruple = (x) => 4 * x;// Composed functions for multiplication of specific valuesconst multiply6 = pipe(double, triple);const multiply9 = pipe(triple, triple);const multiply16 = pipe(quadruple, quadruple);const multiply24 = pipe(double, triple, quadruple);// Usagemultiply6(6); // 36multiply9(9); // 81multiply16(16); // 256multiply24(10); // 240

Ausführen von Promises in der Reihenfolge

Promise-Sequenzierung ist im Wesentlichen das in dem vorherigen Abschnitt demonstrierte Funktional-Piping, das jedoch asynchron ausgeführt wird.

js
// Compare this with pipe: fn(acc) is changed to acc.then(fn),// and initialValue is ensured to be a promiseconst asyncPipe =  (...functions) =>  (initialValue) =>    functions.reduce((acc, fn) => acc.then(fn), Promise.resolve(initialValue));// Building blocks to use for compositionconst 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 promisesconst f3 = (a) => a * 3;const p4 = async (a) => a * 4;asyncPipe(p1, p2, f3, p4)(10).then(console.log); // 1200

asyncPipe kann auch mitasync/await implementiert werden, was seine Ähnlichkeit mitpipe besser demonstriert:

js
const asyncPipe =  (...functions) =>  (initialValue) =>    functions.reduce(async (acc, fn) => fn(await acc), initialValue);

Verwendung von reduce() mit dünn besiedelten Arrays

reduce() überspringt fehlende Elemente in dünn besiedelten Arrays, aber es überspringt keineundefined Werte.

js
console.log([1, 2, , 4].reduce((a, b) => a + b)); // 7console.log([1, 2, undefined, 4].reduce((a, b) => a + b)); // NaN

Aufrufen von reduce() bei Nicht-Array-Objekten

Diereduce() Methode liest dielength-Eigenschaft vonthis und greift dann auf jede Eigenschaft zu, deren Schlüssel eine nicht-negative Ganzzahl kleiner alslength ist.

js
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

Wann man reduce() nicht verwenden sollte

Allzweck-Higher-Order-Funktionen wiereduce() können mächtig, aber manchmal schwer zu verstehen sein, besonders für weniger erfahrene JavaScript-Entwickler. Wenn der Code bei der Verwendung anderer Array-Methoden klarer wird, müssen Entwickler den Lesbarkeitskompromiss gegen die anderen Vorteile der Verwendung vonreduce() abwägen.

Beachten Sie, dassreduce() immer gleichwertig zu einerfor...of-Schleife ist, außer dass anstatt einer Variable im oberen Gültigkeitsbereich zu ändern, nun bei jeder Iteration der neue Wert zurückgegeben wird:

js
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 erwähnt, kann es sein, dass Leutereduce() verwenden möchten, um funktionale Programmierungspraktiken von unveränderlichen Daten nachzuahmen. Entwickler, die die Unveränderlichkeit des Akkumulators aufrechterhalten, kopieren daher oft den gesamten Akkumulator bei jeder Iteration, wie folgt:

js
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 gesamteallNames-Objekt kopieren muss, das abhängig von der Anzahl der eindeutigen Namen groß sein könnte. Dieser Code hat eine Worst-Case-Performance vonO(N^2), wobeiN die Länge vonnames ist.

Eine bessere Alternative ist es, dasallNames-Objekt bei jeder Iteration zuverändern. WennallNames jedoch sowieso verändert wird, sollten Siereduce() in einefor-Schleife umwandeln, was viel klarer ist:

js
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));
js
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, können Sie versehentlich quadratische Komplexität in Ihren Code einführen, was zu einer schnellen Verschlechterung der Leistung bei großen Datenmengen führt. Dies ist im realen Code passiert – siehe zum BeispielMaking Tanstack Table 1000x faster with a 1 line change.

Einige der akzeptablen Anwendungsfälle vonreduce() sind oben gegeben (insbesondere, das Summieren eines Arrays, Promise-Sequenzierung und Funktion-Piping). Es gibt andere Fälle, in denen es bessere Alternativen zureduce() gibt.

  • Flachlegen eines Arrays von Arrays. Verwenden Sieflat() stattdessen.

    js
    const flattened = array.reduce((acc, cur) => acc.concat(cur), []);
    js
    const flattened = array.flat();
  • Gruppieren von Objekten nach einer Eigenschaft. Verwenden SieObject.groupBy() stattdessen.

    js
    const groups = array.reduce((acc, obj) => {  const key = obj.name;  const curGroup = acc[key] ?? [];  return { ...acc, [key]: [...curGroup, obj] };}, {});
    js
    const groups = Object.groupBy(array, (obj) => obj.name);
  • Zusammenfügen von Arrays, die in einem Array von Objekten enthalten sind. Verwenden SieflatMap() stattdessen.

    js
    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], []);
    js
    const allBooks = friends.flatMap((person) => person.books);
  • Entfernen von Duplikaten in einem Array. Verwenden SieSet undArray.from() stattdessen.

    js
    const uniqArray = array.reduce(  (acc, cur) => (acc.includes(cur) ? acc : [...acc, cur]),  [],);
    js
    const uniqArray = Array.from(new Set(array));
  • Eliminieren oder Hinzufügen von Elementen in einem Array. Verwenden SieflatMap() stattdessen.

    js
    // Takes an array of numbers and splits perfect squares into its square rootsconst 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];}, []);
    js
    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, können Sie auchfilter() verwenden.

  • Suchen nach Elementen oder Testen, ob Elemente eine Bedingung erfüllen. Verwenden Siefind() undfindIndex(), odersome() undevery() stattdessen. Diese Methoden haben den zusätzlichen Vorteil, dass sie zurückgeben, sobald das Ergebnis sicher ist, ohne das komplette Array zu durchlaufen.

    js
    const allEven = array.reduce((acc, cur) => acc && cur % 2 === 0, true);
    js
    const allEven = array.every((val) => val % 2 === 0);

In Fällen, in denenreduce() die beste Wahl ist, können Dokumentationen und semantische Variablennamen helfen, Lesbarkeitsnachteile zu minimieren.

Spezifikationen

Specification
ECMAScript® 2026 Language Specification
# sec-array.prototype.reduce

Browser-Kompatibilität

Siehe auch

Help improve MDN

Learn how to contribute Diese Seite wurde automatisch aus dem Englischen übersetzt.

[8]ページ先頭

©2009-2025 Movatter.jp