17. Die for-of-Schleife
Inhaltsverzeichnis
Bitte unterstützen Sie dieses Buch: kaufen Sie es (PDF, EPUB, MOBI) oder spenden Sie
(Werbung, bitte nicht blockieren.)

17. Die for-of-Schleife



17.1 Überblick

for-of ist eine neue Schleife in ES6, die sowohl for-in als auch forEach() ersetzt und das neue Iterationsprotokoll unterstützt.

Verwenden Sie sie, um über *iterierbare* Objekte (Arrays, Strings, Maps, Sets usw.; siehe Kap. „Iterables und Iteratoren“) zu iterieren.

const iterable = ['a', 'b'];
for (const x of iterable) {
    console.log(x);
}

// Output:
// a
// b

break und continue funktionieren innerhalb von for-of-Schleifen.

for (const x of ['a', '', 'b']) {
    if (x.length === 0) break;
    console.log(x);
}

// Output:
// a

Greifen Sie sowohl auf Elemente als auch auf deren Indizes zu, während Sie über ein Array iterieren (die eckigen Klammern vor of bedeuten, dass wir Destrukturierung verwenden).

const arr = ['a', 'b'];
for (const [index, element] of arr.entries()) {
    console.log(`${index}. ${element}`);
}

// Output:
// 0. a
// 1. b

Iterieren Sie über die [Schlüssel, Wert]-Einträge in einer Map (die eckigen Klammern vor of bedeuten, dass wir Destrukturierung verwenden).

const map = new Map([
    [false, 'no'],
    [true, 'yes'],
]);
for (const [key, value] of map) {
    console.log(`${key} => ${value}`);
}

// Output:
// false => no
// true => yes

17.2 Einführung in die for-of-Schleife

for-of ermöglicht es Ihnen, über Datenstrukturen zu iterieren, die *iterierbar* sind: Arrays, Strings, Maps, Sets und andere. Wie genau Iterierbarkeit funktioniert, wird in Kap. „Iterables und Iteratoren“ erklärt. Aber Sie müssen die Details nicht kennen, wenn Sie die for-of-Schleife verwenden.

const iterable = ['a', 'b'];
for (const x of iterable) {
    console.log(x);
}

// Output:
// a
// b

for-of durchläuft die Elemente von iterable und weist sie nacheinander der Schleifenvariablen x zu, bevor es den Schleifenkörper ausführt. Der Geltungsbereich von x ist die Schleife, es existiert nur darin.

Sie können break und continue verwenden.

for (const x of ['a', '', 'b']) {
    if (x.length === 0) break;
    console.log(x);
}

// Output:
// a

for-of kombiniert die Vorteile von

17.3 Fallstrick: for-of funktioniert nur mit iterierbaren Werten

Der Operand der of-Klausel muss iterierbar sein. Das bedeutet, dass Sie eine Hilfsfunktion benötigen, wenn Sie über einfache Objekte iterieren möchten (siehe „Einfache Objekte sind nicht iterierbar“). Wenn ein Wert Array-ähnlich ist, können Sie ihn über Array.from() in ein Array konvertieren.

// Array-like, but not iterable!
const arrayLike = { length: 2, 0: 'a', 1: 'b' };

for (const x of arrayLike) { // TypeError
    console.log(x);
}

for (const x of Array.from(arrayLike)) { // OK
    console.log(x);
}

17.4 Iterationsvariablen: const-Deklarationen im Vergleich zu var-Deklarationen

Wenn Sie die Iterationsvariable als const deklarieren, wird für jede Iteration eine neue *Bindung* (Speicherplatz) erstellt. Das zeigt sich im folgenden Code-Snippet, in dem wir die aktuelle Bindung von elem für später über eine Pfeilfunktion speichern. Danach sehen Sie, dass die Pfeilfunktionen nicht dieselbe Bindung für elem teilen, sondern jede eine andere hat.

const arr = [];
for (const elem of [0, 1, 2]) {
    arr.push(() => elem); // save `elem` for later
}
console.log(arr.map(f => f())); // [0, 1, 2]

// `elem` only exists inside the loop:
console.log(elem); // ReferenceError: elem is not defined

Eine let-Deklaration funktioniert genauso wie eine const-Deklaration (aber die Bindungen sind veränderbar).

Es ist lehrreich zu sehen, wie sich die Dinge unterscheiden, wenn Sie die Iterationsvariable mit var deklarieren. Nun beziehen sich alle Pfeilfunktionen auf dieselbe Bindung von elem.

const arr = [];
for (var elem of [0, 1, 2]) {
    arr.push(() => elem);
}
console.log(arr.map(f => f())); // [2, 2, 2]

// `elem` exists in the surrounding function:
console.log(elem); // 2

Eine Bindung pro Iteration ist sehr hilfreich, wenn Sie Funktionen über eine Schleife erstellen (z. B. um Ereignis-Listener hinzuzufügen).

Sie erhalten auch pro Iteration Bindungen in for-Schleifen (über let) und for-in-Schleifen (über const oder let). Details werden im Kapitel über Variablen erklärt.

17.5 Iterieren mit vorhandenen Variablen, Objekteigenschaften und Array-Elementen

Bisher haben wir nur for-of mit einer deklarierten Iterationsvariablen gesehen. Aber es gibt mehrere andere Formen.

Sie können mit einer vorhandenen Variablen iterieren.

let x;
for (x of ['a', 'b']) {
    console.log(x);
}

Sie können auch mit einer Objekteigenschaft iterieren.

const obj = {};
for (obj.prop of ['a', 'b']) {
    console.log(obj.prop);
}

Und Sie können mit einem Array-Element iterieren.

const arr = [];
for (arr[0] of ['a', 'b']) {
    console.log(arr[0]);
}

17.6 Iterieren mit einem Destrukturierungsmuster

Die Kombination von for-of mit Destrukturierung ist besonders nützlich für Iterables über [Schlüssel, Wert]-Paare (als Arrays kodiert). Das sind Maps.

const map = new Map().set(false, 'no').set(true, 'yes');
for (const [k,v] of map) {
    console.log(`key = ${k}, value = ${v}`);
}
// Output:
// key = false, value = no
// key = true, value = yes

Array.prototype.entries() gibt ebenfalls ein Iterable über [Schlüssel, Wert]-Paare zurück.

const arr = ['a', 'b', 'c'];
for (const [k,v] of arr.entries()) {
    console.log(`key = ${k}, value = ${v}`);
}
// Output:
// key = 0, value = a
// key = 1, value = b
// key = 2, value = c

Daher bietet Ihnen entries() eine Möglichkeit, iterierte Elemente unterschiedlich zu behandeln, je nach ihrer Position.

/** Same as arr.join(', ') */
function toString(arr) {
    let result = '';
    for (const [i,elem] of arr.entries()) {
        if (i > 0) {
            result += ', ';
        }
        result += String(elem);
    }
    return result;
}

Diese Funktion wird wie folgt verwendet.

> toString(['eeny', 'meeny', 'miny', 'moe'])
'eeny, meeny, miny, moe'
Weiter: 18. Neue Array-Features