TypeError: 'x' ist nicht iterierbar

Der JavaScript-Fehler "ist nicht iterierbar" tritt auf, wenn der Wert, der mit dem Spread-Operator in ein Array oder einen Funktionsaufruf übergeben wird, der als rechte Seite von for...of verwendet wird, als Argument einer Funktion wie Promise.all oder Set(), oder als rechte Seite einer Array-Destrukturierung angegeben ist, kein iterierbares Objekt ist. Dieser Fehler tritt auch auf, wenn Array.fromAsync() oder for await...of mit einem nicht-asynchronen iterierbaren verwendet wird.

Nachricht

TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function (V8-based & Safari)
TypeError: %Array%.from requires that the property of the first argument, items[Symbol.iterator], when exists, be a function (V8-based & Safari)
TypeError: Array.fromAsync requires that the property of the first argument, items[Symbol.asyncIterator], when exists, be a function (V8-based & Safari)
TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator)) (V8-based)
TypeError: x is not async iterable (V8-based)
TypeError: x is not iterable (V8-based & Firefox)
TypeError: undefined is not a function (near '...y of x...') (Safari)
TypeError: Array.from: no function (Safari)
TypeError: Type error (Safari)

Fehlertyp

Was ist schiefgelaufen?

Der Wert, der mit dem Spread-Operator in ein Array oder einen Funktionsaufruf übergeben wird, der als rechte Seite von for...of verwendet wird, oder als Argument einer Funktion wie Promise.all oder Set(), oder als Quelle eines Array-Destrukturierungsmusters angegeben ist, ist kein iterierbares Objekt. Ein iterierbares Objekt kann ein eingebauter iterierbarer Typ wie Array, String oder Map, ein Generator-Ergebnis oder ein Objekt sein, das das iterierbare Protokoll implementiert.

js
const nonIterable1 = {};
const nonIterable2 = { [Symbol.iterator]: 1 };

[...nonIterable1];
Math.max(...nonIterable1);
for (const x of nonIterable1);
new Set(nonIterable1);
Array.from(nonIterable2);
new Int8Array(nonIterable2);
const [] = nonIterable1;

Beispiele

Array-Destrukturierung eines nicht-iterierbaren Elements

js
const myObj = { arrayOrObjProp1: {}, arrayOrObjProp2: [42] };

const {
  arrayOrObjProp1: [value1],
  arrayOrObjProp2: [value2],
} = myObj; // TypeError: object is not iterable

console.log(value1, value2);

Das nicht-iterierbare Element kann in einigen Laufzeitumgebungen undefined sein.

Iterieren über Objekteigenschaften

In JavaScript sind Objecte nicht iterierbar, es sei denn, sie implementieren das iterierbare Protokoll. Daher können Sie for...of nicht verwenden, um über die Eigenschaften eines Objekts zu iterieren.

js
const obj = { France: "Paris", England: "London" };
for (const p of obj) {
  // …
} // TypeError: obj is not iterable

Stattdessen müssen Sie Object.keys oder Object.entries verwenden, um über die Eigenschaften oder Einträge eines Objekts zu iterieren.

js
const obj = { France: "Paris", England: "London" };
// Iterate over the property names:
for (const country of Object.keys(obj)) {
  const capital = obj[country];
  console.log(country, capital);
}

for (const [country, capital] of Object.entries(obj)) {
  console.log(country, capital);
}

Eine weitere Möglichkeit für diesen Anwendungsfall wäre die Verwendung eines Map:

js
const map = new Map();
map.set("France", "Paris");
map.set("England", "London");
// Iterate over the property names:
for (const country of map.keys()) {
  const capital = map.get(country);
  console.log(country, capital);
}

for (const capital of map.values()) {
  console.log(capital);
}

for (const [country, capital] of map.entries()) {
  console.log(country, capital);
}

Iterieren über einen Generator

Generator-Funktionen sind Funktionen, die Sie aufrufen, um ein iterierbares Objekt zu erzeugen.

js
function* generate(a, b) {
  yield a;
  yield b;
}

for (const x of generate) {
  console.log(x);
} // TypeError: generate is not iterable

Wenn sie nicht aufgerufen werden, ist das mit dem Generator korrespondierende Function-Objekt aufrufbar, aber nicht iterierbar. Das Aufrufen eines Generators erzeugt ein iterierbares Objekt, das über die während der Ausführung des Generators erzeugten Werte iteriert.

js
function* generate(a, b) {
  yield a;
  yield b;
}

for (const x of generate(1, 2)) {
  console.log(x);
}

Iterieren über ein benutzerdefiniertes Iterierbares

Benutzerdefinierte Iterierbare können erstellt werden, indem die Symbol.iterator-Methode implementiert wird. Sie müssen sicherstellen, dass Ihre Iterator-Methode ein Objekt zurückgibt, das ein Iterator ist, was bedeutet, dass es eine next-Methode haben muss.

js
const myEmptyIterable = {
  [Symbol.iterator]() {
    return []; // [] is iterable, but it is not an iterator — it has no next method.
  },
};

Array.from(myEmptyIterable); // TypeError: myEmptyIterable is not iterable

Hier ist eine korrekte Implementierung:

js
const myEmptyIterable = {
  [Symbol.iterator]() {
    return [][Symbol.iterator]();
  },
};

Array.from(myEmptyIterable); // []

Siehe auch