for-of-Schleife for-of-Schleifefor-of funktioniert nur mit iterierbaren Wertenconst-Deklarationen im Vergleich zu var-Deklarationenfor-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
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
for-Schleifen: break/continue; verwendbar in GeneratorenforEach()-Methoden: prägnante Syntaxfor-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);
}
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.
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]);
}
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'