TypeError: Reduce von leerem Array ohne Anfangswert
Der JavaScript-Fehler "reduce von leerem Array ohne Anfangswert" tritt auf, wenn eine reduce-Funktion verwendet wird.
Meldung
TypeError: Reduce of empty array with no initial value (V8-based & Firefox & Safari)
Fehlertyp
TypeError
Was ist schiefgelaufen?
In JavaScript gibt es mehrere reduce-Funktionen:
Array.prototype.reduce(),Array.prototype.reduceRight()undTypedArray.prototype.reduce(),TypedArray.prototype.reduceRight()).
Diese Funktionen nehmen optional einen initialValue an (der als
erstes Argument beim ersten Aufruf des callback verwendet wird). Wenn jedoch kein Anfangswert angegeben wird, wird das erste Element des Array oder
TypedArray als Anfangswert verwendet. Dieser Fehler tritt auf, wenn ein leeres Array übergeben wird, da in diesem Fall kein Anfangswert zurückgegeben werden kann.
Beispiele
>Ungültige Fälle
Dieses Problem tritt häufig auf, wenn es mit einem Filter kombiniert wird
(Array.prototype.filter(), TypedArray.prototype.filter())
der alle Elemente der Liste entfernt. Somit bleibt kein Element übrig, das als Anfangswert verwendet werden könnte.
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.
Ähnlicherweise kann dasselbe Problem auftreten, wenn ein Tippfehler in einem Selektor vorliegt oder eine unerwartete Anzahl von Elementen in einer Liste vorhanden ist:
const names = document.getElementsByClassName("names");
const nameList = 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.
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 wäre, den Leerfall zu behandeln, entweder vor dem Aufruf von
reduce, oder im Callback nach dem Hinzufügen eines unerwarteten Dummys als Anfangswert.
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.