Start · Sprachen · JavaScript · Referenz · Iterator.prototype[Symbol.iterator]()

Iterator.prototype[Symbol.iterator]()

Methode

Gibt den Iterator selbst (<code>this</code>) zurück und macht so jeden eingebauten Iterator zugleich zu einem Iterable, das von <code>for...of</code>, Spread &amp; Co. konsumiert werden kann.

seit JavaScript ES2015 Kategorie: method-property

Signatur

Iterator.prototype[Symbol.iterator]()

Beschreibung

Die Methode [Symbol.iterator]() auf Iterator.prototype implementiert das Iterable-Protokoll für alle eingebauten Iteratoren. Ihre Implementierung ist trivial: Sie gibt einfach this zurück. Dadurch ist jeder Iterator (z. B. von Array.prototype.values(), Map.prototype.entries(), String.prototype[Symbol.iterator]() oder Generator-Objekten) gleichzeitig ein Iterable.

Das ist der Grund, warum man Iteratoren direkt an Syntax übergeben kann, die ein Iterable erwartet: for...of, den Spread-Operator ..., Destrukturierung, yield*, Array.from(), new Map(), new Set(), Promise.all() usw. Diese Konstrukte rufen intern zuerst [Symbol.iterator]() auf und erhalten so den Iterator selbst zurück.

Eigene Iterator-Klassen, die von Iterator erben (class MyIter extends Iterator) oder deren Prototyp-Kette Iterator.prototype enthält, bekommen dieses Verhalten automatisch geschenkt. Wichtig: Weil derselbe Iterator zurückgegeben wird, ist ein Iterator nur einmal durchlaufbar – nach dem ersten vollständigen Durchlauf ist er erschöpft.

Rückgabewert

Typ
Iterator
Beschreibung
Der Wert von this – also das Iterator-Objekt selbst, keine Kopie und kein neuer Iterator.

Beispiele

Iterator gibt sich selbst zurück

const iter = [10, 20, 30].values();
console.log(iter[Symbol.iterator]() === iter);

// Deshalb funktioniert for...of direkt auf dem Iterator
for (const n of iter) {
  console.log(n);
}
true 10 20 30

Iterator ist nur einmal konsumierbar

const entries = new Map([['a', 1], ['b', 2]]).entries();

const first = [...entries];
const second = [...entries]; // gleicher, bereits erschöpfter Iterator

console.log(first);
console.log(second);
[ [ 'a', 1 ], [ 'b', 2 ] ] []

Teilweise konsumieren und Rest weiterverarbeiten

// CSV-Zeilen: erste Zeile ist Kopfzeile
const lines = 'name,alter\nAnna,31\nBen,27'.split('\n')[Symbol.iterator]();

const header = lines.next().value.split(',');

// Rest direkt per for...of – möglich dank [Symbol.iterator]() === this
const rows = [];
for (const line of lines) {
  const values = line.split(',');
  rows.push(Object.fromEntries(header.map((h, i) => [h, values[i]])));
}
console.log(rows);
[ { name: 'Anna', alter: '31' }, { name: 'Ben', alter: '27' } ]

Eigener Iterator erbt das Verhalten von Iterator

class Countdown extends Iterator {
  #n;
  constructor(start) {
    super();
    this.#n = start;
  }
  next() {
    return this.#n > 0
      ? { value: this.#n--, done: false }
      : { value: undefined, done: true };
  }
}

const cd = new Countdown(3);
console.log([...cd]); // [Symbol.iterator] kommt von Iterator.prototype
[ 3, 2, 1 ]

// Wichtig · Fallstricke

  • Einmal-Durchlauf: Da this zurückgegeben wird, liefert ein zweites for...of oder Spread auf demselben Iterator keine Werte mehr. Wer mehrfach iterieren will, sollte das zugrunde liegende Iterable (Array, Map, Set) verwenden oder die Werte mit Array.from() puffern.
  • Vorzeitiger Abbruch: Ein break in for...of ruft return() auf dem Iterator auf (falls vorhanden) – Generatoren werden dadurch beendet und lassen sich danach nicht fortsetzen.
  • Eigene Iteratoren: Handgeschriebene Iterator-Objekte (nur mit next()) sind nicht automatisch iterierbar. Entweder von Iterator erben, Iterator.from() verwenden oder selbst [Symbol.iterator]() { return this; } ergänzen.
  • Kompatibilität: Die Methode existiert auf dem (früher verborgenen) %IteratorPrototype% seit ES2015 in allen Browsern. Das globale Iterator-Objekt samt extends Iterator und Iterator-Helpern ist erst mit ES2025 standardisiert (Chrome 122+, Firefox 131+, Safari 18.4+, Node.js 22+).