Start · Sprachen · JavaScript · Referenz · Symbol.iterator

Symbol.iterator

Eigenschaft

Das wohlbekannte Symbol <code>Symbol.iterator</code> legt fest, welche Methode ein Objekt iterierbar macht – genutzt von <code>for...of</code>, Spread, Destrukturierung und Co.

seit JavaScript ES2015 Kategorie: method-property

Signatur

Symbol.iterator

Beschreibung

Symbol.iterator ist eine statische, nicht beschreibbare Dateneigenschaft von Symbol und enthält eines der wohlbekannten Symbole (well-known symbols). Ein Objekt gilt als iterierbar, wenn es unter dem Schlüssel [Symbol.iterator] eine Methode besitzt, die ein Iterator-Objekt zurückgibt – also ein Objekt mit einer Methode next(), die Ergebnisse der Form { value, done } liefert.

Die Sprache ruft diese Methode automatisch auf bei for...of, dem Spread-Operator ([...obj], fn(...obj)), der Array-Destrukturierung, yield*, Array.from(), new Map(), new Set(), Promise.all() und weiteren Stellen. Eingebaute Typen wie Array, String, Map, Set, TypedArray, arguments sowie DOM-Sammlungen wie NodeList implementieren sie bereits.

Eigene Klassen oder Datenstrukturen (Listen, Bäume, Bereiche) macht man iterierbar, indem man [Symbol.iterator]() definiert – am bequemsten als Generator-Methode *[Symbol.iterator]() { … }. So lassen sich eigene Strukturen nahtlos mit allen Sprachmitteln für Iteration kombinieren.

Die Eigenschaft selbst hat die Attribute writable: false, enumerable: false, configurable: false; ihr Wert ist in jedem Realm (z. B. auch in iframes) dasselbe Symbol.

Rückgabewert

Typ
symbol
Beschreibung
Das wohlbekannte Symbol Symbol.iterator. Die damit hinterlegte Methode wird ohne Argumente aufgerufen und muss ein Iterator-Objekt (mit next()) zurückgeben.

Beispiele

Eingebauten Iterator manuell verwenden

const farben = ['rot', 'grün'];
const it = farben[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
{ value: 'rot', done: false } { value: 'grün', done: false } { value: undefined, done: true }

Eigene Klasse per Generator iterierbar machen

class Bereich {
  constructor(start, ende, schritt = 1) {
    this.start = start;
    this.ende = ende;
    this.schritt = schritt;
  }

  *[Symbol.iterator]() {
    for (let i = this.start; i <= this.ende; i += this.schritt) {
      yield i;
    }
  }
}

const r = new Bereich(1, 10, 3);
for (const n of r) console.log(n);
console.log([...r]);
const [erstes, zweites] = r;
console.log(erstes, zweites);
1 4 7 10 [ 1, 4, 7, 10 ] 1 4

Iterator-Protokoll von Hand implementieren (verkettete Liste)

const liste = {
  kopf: { wert: 'a', next: { wert: 'b', next: { wert: 'c', next: null } } },
  [Symbol.iterator]() {
    let knoten = this.kopf;
    return {
      next: () => {
        if (!knoten) return { value: undefined, done: true };
        const value = knoten.wert;
        knoten = knoten.next;
        return { value, done: false };
      },
      // Optional: wird bei break/return/throw aufgerufen
      return: () => {
        console.log('Aufräumen');
        return { value: undefined, done: true };
      }
    };
  }
};

for (const w of liste) {
  console.log(w);
  if (w === 'b') break;
}
a b Aufräumen

Prüfen, ob ein Wert iterierbar ist

const istIterierbar = (wert) =>
  wert != null && typeof wert[Symbol.iterator] === 'function';

console.log(istIterierbar([1, 2]));
console.log(istIterierbar('Text'));
console.log(istIterierbar(new Map()));
console.log(istIterierbar({ a: 1 }));
console.log(istIterierbar(42));
true true true false false

// Wichtig · Fallstricke

  • Einfache Objekte sind nicht iterierbar: for (const x of { a: 1 }) wirft TypeError: … is not iterable. Für Objekte Object.entries(), Object.keys() oder Object.values() verwenden.
  • Rückgabe muss ein Objekt sein: Liefert [Symbol.iterator]() keinen Iterator bzw. next() kein Objekt, entsteht ein TypeError. Eine normale Funktion ist nötig – keine Arrow-Funktion, wenn this auf die Instanz zeigen soll.
  • Einmal-Iteratoren: Generator-Objekte geben bei [Symbol.iterator]() sich selbst zurück und sind nach einem Durchlauf erschöpft. Eine Klasse mit Generator-Methode liefert dagegen bei jedem Durchlauf einen frischen Iterator.
  • Überschreiben eingebauter Iteratoren (z. B. Array.prototype[Symbol.iterator]) verändert das Verhalten von Spread und for...of global und kann Performance-Optimierungen der Engine aushebeln – vermeiden.
  • Unendliche Iteratoren sind erlaubt, dürfen aber nicht mit Spread oder Array.from() vollständig ausgelesen werden (Endlosschleife).
  • Für asynchrone Datenquellen gibt es das Gegenstück Symbol.asyncIterator mit for await...of.
  • Kompatibilität: ES2015, in allen modernen Browsern und Node.js unterstützt; nicht im Internet Explorer.