TypeError: Reduce eines leeren Arrays ohne initialen Wert

Die JavaScript-Ausnahme "reduce eines leeren Arrays ohne initialen Wert" tritt auf, wenn eine reduce-Funktion verwendet wird.

Meldung

TypeError: Reduce of empty array with no initial value (V8-based & Firefox & Safari)

Fehlertyp

Was ist schiefgelaufen?

In JavaScript gibt es mehrere reduce-Funktionen:

Diese Funktionen nehmen optional einen initialValue an (der als erstes Argument für den ersten Aufruf des callback verwendet wird). Wenn jedoch kein initialer Wert angegeben wird, wird das erste Element des Array oder TypedArray als initialer Wert verwendet. Dieser Fehler tritt auf, wenn ein leeres Array bereitgestellt wird, da in diesem Fall kein initialer Wert zurückgegeben werden kann.

Beispiele

Ungültige Fälle

Dieses Problem tritt häufig auf, wenn es in Kombination mit einer Filterfunktion (Array.prototype.filter(), TypedArray.prototype.filter()) verwendet wird, die alle Elemente der Liste entfernt. Somit bleibt kein Wert, der als initialer Wert verwendet werden kann.

js
const ints = [0, -1, -2, -3, -4, -5];
ints
  .filter((x) => x > 0) // removes all elements
  .reduce((x, y) => x + y); // no more elements to use for the initial value.

Ähnlich kann das gleiche Problem auftreten, wenn ein Tippfehler im Selektor vorliegt oder wenn eine unerwartete Anzahl von Elementen in der Liste vorhanden ist:

js
const names = document.getElementsByClassName("names");
const name_list = Array.prototype.reduce.call(
  names,
  (acc, name) => acc + ", " + name,
);

Gültige Fälle

Diese Probleme können auf zwei verschiedene Arten gelöst werden.

Eine Möglichkeit besteht darin, tatsächlich einen initialValue als neutrales Element des Operators anzugeben, wie 0 für die Addition, 1 für eine Multiplikation oder einen leeren String für eine Verkettung.

js
const ints = [0, -1, -2, -3, -4, -5];
ints
  .filter((x) => x > 0) // removes all elements
  .reduce((x, y) => x + y, 0); // the initial value is the neutral element of the addition

Eine andere Möglichkeit besteht darin, den leeren Fall zu behandeln, entweder vor dem Aufruf von reduce oder im Callback, nachdem ein unerwarteter Dummy-Initialwert hinzugefügt wurde.

js
const names = document.getElementsByClassName("names");

let nameList1 = "";
if (names.length >= 1) {
  nameList1 = Array.prototype.reduce.call(
    names,
    (acc, name) => `${acc}, ${name}`,
  );
}
// nameList1 === "" when names is empty.

const nameList2 = Array.prototype.reduce.call(
  names,
  (acc, name) => {
    if (acc === "")
      // initial value
      return name;
    return `${acc}, ${name}`;
  },
  "",
);
// nameList2 === "" when names is empty.

Siehe auch