Was for...of durchlaufen kann, nennt man iterierbar: Arrays, Strings, Maps, Sets und mehr. Du kannst auch eigene iterierbare Objekte bauen, am einfachsten mit Generatoren.
Das Iterator-Protokoll
Ein Iterator ist ein Objekt mit einer Methode next(), die { value, done } liefert:
Ergebnis
{ value: 10, done: false }
{ value: 20, done: false }
{ value: undefined, done: true }for...of, Spread (...), Destructuring und Array.from nutzen dieses Protokoll.
Generatoren: function*
Eine Generatorfunktion (function*) liefert Werte mit yield nacheinander und pausiert dazwischen:
Ergebnis
[ 1, 2, 3, 4, 5 ]
Wert 1
Wert 2
Wert 3
{ value: 1, done: false } { value: 2, done: false } { value: undefined, done: true }Der Code läuft erst weiter, wenn der nächste Wert angefordert wird (Lazy Evaluation). Dadurch sind auch unendliche Folgen möglich:
Ergebnis
[ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]
Eigene iterierbare Klassen
Ergebnis
[ 3, 4, 5, 6, 7 ] 7 3 5 7
yield* und Werte in den Generator senden
Ergebnis
[ 1, 'a', 'b', 2 ]
Wie heißt du?
Hallo Mia, wie alt bist du?
{ value: 'Mia ist 17', done: true }Nützliche Muster
Ergebnis
[ 1, 9, 25, 49, 81 ] [ 2, 4, 6 ]
Asynchrone Iteratoren
Mit async function* und for await...of verarbeitest du Daten, die nach und nach eintreffen, etwa gelesene Dateistücke oder Seiten einer API:
Ergebnis
Seite 1 Seite 2 Seite 3
Merke
- Iterierbare Objekte haben
[Symbol.iterator](), Iteratorennext() function*undyielderzeugen Werte nacheinander und pausieren dazwischen- Generatoren sind lazy und können unendlich sein
yield*delegiert an einen anderen Iterierbarenasync function*undfor await...offür Datenströme
Aufgabe
Schreibe einen Generator primzahlen(), der unendlich viele Primzahlen liefert, und gib die ersten zehn aus.