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

Array.prototype[Symbol.iterator]()

Methode

Gibt einen Array-Iterator zurück, der die Werte des Arrays liefert, und macht Arrays damit zu Iterables für <code>for...of</code>, Spread und Destrukturierung.

seit JavaScript ES2015 Kategorie: method-property

Signatur

Array.prototype[Symbol.iterator]()

Beschreibung

Die Methode [Symbol.iterator]() von Array-Instanzen setzt das Iterable-Protokoll um. Überall, wo JavaScript ein Iterable erwartet, wird sie im Hintergrund aufgerufen. Das betrifft for...of-Schleifen, die Spread-Syntax ([...arr]), die Array-Destrukturierung, Array.from(), new Set(arr), new Map(arr), Promise.all() und yield*.

Diese Methode ist dieselbe Funktion wie Array.prototype.values(), es gilt also Array.prototype[Symbol.iterator] === Array.prototype.values. Zurück kommt ein neues Array-Iterator-Objekt. Dessen next()-Methode liefert Objekte der Form { value, done }, und zwar für jeden Index von 0 bis length - 1.

Direkt aufrufen muss man die Methode nur selten. Das lohnt sich, wenn du einen Iterator von Hand weiterschalten willst, etwa um das erste Element getrennt zu verarbeiten oder um Werte schrittweise zu verbrauchen. Außerdem kannst du die Methode überschreiben, um eigene Iterationslogik festzulegen. Das ist allerdings selten sinnvoll und kann eingebaute Funktionen beeinflussen.

Der Iterator ist live: Er prüft bei jedem Schritt die aktuelle length und liest den aktuellen Wert. Änderst du das Array während der Iteration, wirkt sich das auf die weiteren Werte aus.

Rückgabewert

Typ
Iterator<any> (Array Iterator)
Beschreibung
Ein neues iterierbares Iterator-Objekt, das nacheinander die Werte aller Indizes des Arrays liefert. Leere Plätze (Löcher) in dünn besetzten Arrays liefert es als undefined.

Beispiele

Implizite Nutzung durch for...of und Spread

const farben = ['rot', 'grün', 'blau'];

// for...of ruft intern farben[Symbol.iterator]() auf
for (const farbe of farben) {
  console.log(farbe);
}

// Spread und Destrukturierung ebenso
const kopie = [...farben];
const [erste, ...rest] = farben;
console.log(kopie, erste, rest);
rot grün blau [ 'rot', 'grün', 'blau' ] rot [ 'grün', 'blau' ]

Iterator manuell mit next() weiterschalten

const zahlen = [10, 20, 30];
const it = zahlen[Symbol.iterator]();

console.log(it.next()); // { value: 10, done: false }
console.log(it.next()); // { value: 20, done: false }
console.log(it.next()); // { value: 30, done: false }
console.log(it.next()); // { value: undefined, done: true }
{ value: 10, done: false } { value: 20, done: false } { value: 30, done: false } { value: undefined, done: true }

Praxis: CSV-Kopfzeile getrennt verarbeiten

const zeilen = [
  'name;alter',
  'Anna;31',
  'Ben;27'
];

const it = zeilen[Symbol.iterator]();
const kopf = it.next().value.split(';');

// Der Rest-Iterator ist selbst iterierbar
const datensaetze = [];
for (const zeile of it) {
  const werte = zeile.split(';');
  datensaetze.push(Object.fromEntries(kopf.map((k, i) => [k, werte[i]])));
}
console.log(datensaetze);
[ { name: 'Anna', alter: '31' }, { name: 'Ben', alter: '27' } ]

Generische Funktion: prüfen, ob ein Wert iterierbar ist

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

console.log(istIterierbar([1, 2]));        // true
console.log(istIterierbar('abc'));         // true
console.log(istIterierbar({ a: 1 }));      // false
console.log(Array.prototype[Symbol.iterator] === Array.prototype.values);
true true false true

// Wichtig · Fallstricke

  • Identisch mit values(): Array.prototype[Symbol.iterator] und Array.prototype.values sind dasselbe Funktionsobjekt.
  • Einmal verbrauchbar: Ein Iterator lässt sich nur einmal durchlaufen. Wenn du ein zweites Mal iterieren willst, musst du arr[Symbol.iterator]() erneut aufrufen. Das Array selbst kannst du dagegen beliebig oft iterieren.
  • Live-Verhalten: Elemente, die während der Iteration angehängt werden, liefert der Iterator mit. Beim Entfernen werden Elemente übersprungen. Deshalb das Array beim Iterieren nicht verändern.
  • Löcher: Anders als forEach() überspringt der Iterator leere Plätze nicht, sondern liefert dort undefined.
  • Überschreiben ist riskant: Überschreibst du Array.prototype[Symbol.iterator], ändert sich das Verhalten von Spread, Destrukturierung, Array.from() usw. im ganzen Programm. Außerdem kann das Optimierungen der Engine ausschalten.
  • Generisch: Die Methode funktioniert auch mit array-ähnlichen Objekten, z. B. Array.prototype[Symbol.iterator].call({ length: 2, 0: 'a', 1: 'b' }).
  • Kompatibilität: Wird seit ES2015 von allen modernen Browsern und von Node.js unterstützt. Der Internet Explorer unterstützt die Methode nicht, dort sind Polyfills nötig (z. B. core-js).