Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Iteratoren und Generatoren in JavaScript

Iteratoren und Generatoren in JavaScript

~13 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026

Wir haben for...of seit Kapitel 7 auf Arrays angewendet, ohne zu fragen, WARUM das funktioniert. Dieses Kapitel beantwortet das – und zeigt, wie wir unserem eigenen Haushaltsbuch-Kontentyp dieselbe Fähigkeit verleihen.

Das Iterator-Protokoll

for...of funktioniert auf JEDEM Wert, der das "iterable"-Protokoll erfüllt: ein Objekt mit einer Methode unter dem speziellen Schlüssel Symbol.iterator, die einen ITERATOR zurückgibt – ein Objekt mit einer next()-Methode, die bei jedem Aufruf { value, done } liefert.

const betraege = [100, 200, 300];
const iterator = betraege[Symbol.iterator]();

console.log(iterator.next()); // { value: 100, done: false }
console.log(iterator.next()); // { value: 200, done: false }
console.log(iterator.next()); // { value: 300, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

GENAU das passiert intern bei JEDEM for...of-Durchlauf – die Schleife ruft wiederholt next() auf, bis done: true zurückkommt. Arrays, Strings, Map und Set implementieren dieses Protokoll bereits von Haus aus.

Generator-Funktionen: Iteratoren einfach bauen

Ein Iterator von Hand zu schreiben (wie oben) ist umständlich. Generator-Funktionen (erkennbar am function*) übernehmen das Verwalten von { value, done } automatisch – yield "pausiert" die Funktion und gibt einen Wert aus, bis next() erneut aufgerufen wird:

function* zaehleMonate(von, bis) {
  for (let monat = von; monat <= bis; monat++) {
    yield monat;
  }
}

for (const monat of zaehleMonate(1, 3)) {
  console.log(monat); // 1, dann 2, dann 3
}

// Auch manuell steuerbar, wie ein normaler Iterator:
const gen = zaehleMonate(1, 3);
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }

Praxisbeispiel: eine eigene iterierbare Konten-Sammlung

Damit statten wir eine Sammlung von Konten mit Symbol.iterator aus – so lässt sich direkt for...of darauf anwenden, statt eine separate getAlleKonten()-Methode zu brauchen:

src/kontensammlung.js
export class Kontensammlung {
  #konten = [];

  hinzufuegen(konto) {
    this.#konten.push(konto);
  }

  *[Symbol.iterator]() { // Generator-Methoden-Shorthand innerhalb einer Klasse
    for (const konto of this.#konten) {
      yield konto;
    }
  }
}
import { Kontensammlung } from './kontensammlung.js';

const sammlung = new Kontensammlung();
sammlung.hinzufuegen(new Konto('Girokonto', 1500));
sammlung.hinzufuegen(new Sparkonto('Tagesgeld', 5000, 2.5));

for (const konto of sammlung) { // funktioniert DANK Symbol.iterator, wie bei einem Array!
  console.log(konto.formatiereKontostand());
}

Tipp: Auch der Spread-Operator ([...sammlung]) und Array-Destructuring funktionieren automatisch mit JEDEM iterierbaren Objekt – ein weiterer Vorteil, das Protokoll zu implementieren, statt nur eine Getter-Methode anzubieten.

Generatoren für (theoretisch) unendliche Sequenzen

Ein Vorteil von Generatoren gegenüber Arrays: Werte werden erst bei Bedarf erzeugt ("lazy"), sodass sich auch unendliche Sequenzen modellieren lassen, ohne Speicher zu sprengen:

function* monatsZyklus() {
  const monate = ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'];
  let index = 0;
  while (true) { // läuft unendlich weiter, ist aber unproblematisch dank 'lazy' Auswertung
    yield monate[index % 12];
    index++;
  }
}

const zyklus = monatsZyklus();
console.log(zyklus.next().value); // 'Jan'
console.log(zyklus.next().value); // 'Feb'
// ... würde nach 'Dez' einfach wieder bei 'Jan' weitermachen