Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.
for
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since Juli 2015.
Diefor-Anweisung erstellt eine Schleife, die aus drei optionalen Ausdrücken besteht, die in Klammern eingeschlossen sind und durch Semikolons getrennt werden, gefolgt von einer Anweisung (in der Regel eineBlock-Anweisung), die in der Schleife ausgeführt werden soll.
In diesem Artikel
Probieren Sie es aus
let str = "";for (let i = 0; i < 9; i++) { str += i;}console.log(str);// Expected output: "012345678"Syntax
for (initialization; condition; afterthought) statementinitializationOptionalEin Ausdruck (einschließlichZuweisungsausdrücke) oder eine Variablendeklaration, die einmal ausgewertet wird, bevor die Schleife beginnt. Typischerweise verwendet, um eine Zählervariable zu initialisieren. Dieser Ausdruck kann optional neue Variablen mit den Schlüsseln
varoderletdeklarieren. Mitvardeklarierte Variablen sind nicht lokal zur Schleife, d.h. sie befinden sich im selben Gültigkeitsbereich, in dem diefor-Schleife ist. Mitletdeklarierte Variablen sind lokal zur Anweisung.Das Ergebnis dieses Ausdrucks wird verworfen.
conditionOptionalEin Ausdruck, der vor jedem Schleifendurchlauf ausgewertet wird. Wenn dieser Ausdruckwahr ergibt, wird
statementausgeführt. Wenn der Ausdruckfalsch ergibt, wird die Ausführung der Schleife beendet und es wird zur ersten Anweisung nach derfor-Konstruktion übergegangen.Dieser Bedingungstest ist optional. Wenn weggelassen, ergibt die Bedingung immer wahr.
afterthoughtOptionalEin Ausdruck, der am Ende jedes Schleifendurchlaufs ausgewertet wird. Dies geschieht, bevor die nächste Auswertung der
conditionerfolgt. Wird im Allgemeinen verwendet, um die Zählervariable zu aktualisieren oder zu inkrementieren.statementEin Anweisung, die solange ausgeführt wird, wie die Bedingung wahr ergibt. Sie können eineBlock-Anweisung verwenden, um mehrere Anweisungen auszuführen. Um keine Anweisung innerhalb der Schleife auszuführen, verwenden Sie eineleere Anweisung (
;).
Beschreibung
Wie andere Schleifenanweisungen können SieKontrollflussanweisungen innerhalb vonstatement verwenden:
Beispiele
>Verwendung von for
Die folgendefor-Anweisung beginnt mit der Deklaration der Variableni und ihrer Initialisierung auf0. Sie überprüft, obi kleiner als neun ist, führt die zwei folgenden Anweisungen aus und inkrementierti um 1 nach jedem Durchlauf der Schleife.
for (let i = 0; i < 9; i++) { console.log(i); // more statements}Initialisierungsblock-Syntax
Der Initialisierungsblock akzeptiert sowohl Ausdrücke als auch Variablendeklarationen. Ausdrücke können jedoch nicht denin-Operator ohne Klammern verwenden, da dies mit einerfor...in-Schleife uneindeutig ist.
for (let i = "start" in window ? window.start : 0; i < 9; i++) { console.log(i);}// SyntaxError: 'for-in' loop variable declaration may not have an initializer.// Parenthesize the whole initializerfor (let i = ("start" in window ? window.start : 0); i < 9; i++) { console.log(i);}// Parenthesize the `in` expressionfor (let i = ("start" in window) ? window.start : 0; i < 9; i++) { console.log(i);}Optionale for-Ausdrücke
Alle drei Ausdrücke im Kopf derfor-Schleife sind optional. Zum Beispiel ist es nicht erforderlich, deninitialization-Block zu verwenden, um Variablen zu initialisieren:
let i = 0;for (; i < 9; i++) { console.log(i); // more statements}Wie derinitialization-Block ist auch dercondition-Teil optional. Wenn Sie diesen Ausdruck weglassen, müssen Sie sicherstellen, dass Sie die Schleife im Körper durchbrechen, um keine Endlosschleife zu erzeugen.
for (let i = 0; ; i++) { console.log(i); if (i > 3) break; // more statements}Sie können auch alle drei Ausdrücke weglassen. Stellen Sie sicher, dass Sie einebreak-Anweisung verwenden, um die Schleife zu beenden und auch eine Variable zu ändern (zu erhöhen), so dass die Bedingung für die break-Anweisung irgendwann wahr ist.
let i = 0;for (;;) { if (i > 3) break; console.log(i); i++;}Wenn Sie jedoch nicht alle drei Ausdruckspositionen voll nutzen — insbesondere wenn Sie keine Variablen mit dem ersten Ausdruck deklarieren, sondern etwas im oberen Bereich ändern — sollten Sie stattdessen einewhile-Schleife verwenden, die die Absicht klarer macht.
let i = 0;while (i <= 3) { console.log(i); i++;}Lexikalische Deklarationen im Initialisierungsblock
Das Deklarieren einer Variablen im Initialisierungsblock hat wichtige Unterschiede zur Deklaration im oberenGültigkeitsbereich, insbesondere beim Erstellen einesClosure innerhalb des Schleifenkörpers. Zum Beispiel für den folgenden Code:
for (let i = 0; i < 3; i++) { setTimeout(() => { console.log(i); }, 1000);}Es zeigt0,1 und2 an, wie erwartet. Wenn die Variable jedoch im oberen Bereich definiert ist:
let i = 0;for (; i < 3; i++) { setTimeout(() => { console.log(i); }, 1000);}Es zeigt3,3 und3 an. Der Grund ist, dass jedersetTimeout ein neues Closure erstellt, das diei-Variable umschließt, aber wenn diei-Variable nicht auf den Schleifenkörper beschränkt ist, werden alle Closures auf dieselbe Variable verweisen, wenn sie schließlich aufgerufen werden — und aufgrund der asynchronen Natur vonsetTimeout() geschieht dies, nachdem die Schleife bereits beendet ist, wodurch der Wert voni in allen eingeplanten Rückrufe den Wert3 hat.
Dies passiert auch, wenn Sie einevar-Anweisung als Initialisierung verwenden, da mitvar deklarierte Variablen nur funktionsweit, aber nicht lexikalisch definiert sind (d.h. sie können nicht auf den Schleifenkörper beschränkt werden).
for (var i = 0; i < 3; i++) { setTimeout(() => { console.log(i); }, 1000);}// Logs 3, 3, 3Der Scoping-Effekt des Initialisierungsblocks kann verstanden werden, als ob die Deklaration innerhalb des Schleifenkörpers erfolgt, jedoch zufällig imcondition- undafterthought-Teil zugänglich ist. Genauer gesagt sindlet-Deklarationen speziell fürfor-Schleifen behandelt — wenninitialization einelet-Deklaration ist, dann passiert jedes Mal nach der Auswertung des Schleifenkörpers Folgendes:
- Ein neuer lexikalischer Bereich wird mit neuen
let-deklarierten Variablen erstellt. - Die Bindungswerte aus der letzten Iteration werden verwendet, um die neuen Variablen neu zu initialisieren.
afterthoughtwird im neuen Bereich ausgewertet.
Das erneute Zuweisen der neuen Variablen innerhalb vonafterthought beeinflusst nicht die Bindungen aus der vorherigen Iteration.
Ein neuer lexikalischer Bereich wird auch nachinitialization erstellt, gerade bevorcondition zum ersten Mal ausgewertet wird. Diese Details können beobachtet werden, indem man Closures erstellt, die es ermöglichen, eine Bindung zu einem bestimmten Zeitpunkt zu halten. In diesem Code wird z. B. ein Closure, das iminitialization-Abschnitt erstellt wurde, nicht durch Neubindungen voni imafterthought-Abschnitt aktualisiert:
for (let i = 0, getI = () => i; i < 3; i++) { console.log(getI());}// Logs 0, 0, 0Dies gibt nicht "0, 1, 2" aus, wie es passieren würde, wenngetI im Schleifenkörper deklariert wäre. Das liegt daran, dassgetI nicht bei jeder Iteration neu ausgewertet wird — vielmehr wird die Funktion einmal erstellt und umschließt diei-Variable, die auf die Variable verweist, die bei der ersten Initialisierung der Schleife deklariert wurde. Nachfolgende Aktualisierungen des Wertes voni erstellen tatsächlich neue Variablen namensi, diegetI nicht sieht. Eine Möglichkeit, das zu beheben, besteht darin,getI jedes Mal neu zu berechnen, wenni aktualisiert wird:
for (let i = 0, getI = () => i; i < 3; i++, getI = () => i) { console.log(getI());}// Logs 0, 1, 2Diei-Variable innerhalb derinitialization ist von deri-Variable innerhalb jeder Iteration, einschließlich der ersten, getrennt. In diesem Beispiel gibtgetI 0 zurück, obwohl der Wert voni innerhalb der Iteration vorher erhöht wird:
for (let i = 0, getI = () => i; i < 3; ) { i++; console.log(getI());}// Logs 0, 0, 0Tatsächlich können Sie diese anfängliche Bindung deri-Variable erfassen und später neu zuweisen, und dieser aktualisierte Wert wird nicht im Schleifenkörper sichtbar sein, der die nächste neue Bindung voni sieht.
for ( let i = 0, getI = () => i, incrementI = () => i++; getI() < 3; incrementI()) { console.log(i);}// Logs 0, 0, 0Dies gibt "0, 0, 0" aus, weil diei-Variable in jeder Schleifenbewertung tatsächlich eine separate Variable ist, abergetI undincrementI lesen und schreiben dieanfängliche Bindung voni, nicht das, was anschließend deklariert wurde.
Verwendung von for ohne Körper
Der folgendefor-Zyklus berechnet die Offset-Position eines Knotens imafterthought-Bereich und erfordert daher keinenstatement-Bereich, stattdessen wird ein Semikolon verwendet.
function showOffsetPos(id) { let left = 0; let top = 0; for ( let itNode = document.getElementById(id); // initialization itNode; // condition left += itNode.offsetLeft, top += itNode.offsetTop, itNode = itNode.offsetParent // afterthought ); // semicolon console.log( `Offset position of "${id}" element:left: ${left}px;top: ${top}px;`, );}showOffsetPos("content");// Logs:// Offset position of "content" element:// left: 0px;// top: 153px;Beachten Sie, dass das Semikolon nach derfor-Anweisung obligatorisch ist, da es alsleere Anweisung steht. Andernfalls übernimmt diefor-Anweisung die folgendeconsole.log-Zeile als ihrenstatement-Bereich, wodurch daslog mehrmals ausgeführt wird.
Verwendung von for mit zwei iterierenden Variablen
Sie können zwei Zähler erstellen, die in einer for-Schleife mit demKomma-Operator gleichzeitig aktualisiert werden. Mehrerelet- undvar-Deklarationen können ebenfalls mit Kommata verbunden werden.
const arr = [1, 2, 3, 4, 5, 6];for (let l = 0, r = arr.length - 1; l < r; l++, r--) { console.log(arr[l], arr[r]);}// 1 6// 2 5// 3 4Spezifikationen
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-for-statement> |