for
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Die for
-Anweisung erstellt eine Schleife, die aus drei optionalen Ausdrücken besteht, die in Klammern eingeschlossen und durch Semikolons getrennt sind, gefolgt von einer Anweisung (üblicherweise eine Blockanweisung), die in der Schleife ausgeführt wird.
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)
statement
initialization
Optional-
Ein Ausdruck (einschließlich Zuweisungsausdrücken) oder Variablendeklaration, die einmal vor Beginn der Schleife ausgewertet wird. Wird typischerweise verwendet, um eine Zählvariable zu initialisieren. Dieser Ausdruck kann optional neue Variablen mit den Schlüsselwörtern
var
oderlet
deklarieren. Variablen, die mitvar
deklariert werden, sind nicht lokal zur Schleife, d.h. sie befinden sich im selben Gültigkeitsbereich wie diefor
-Schleife. Variablen, die mitlet
deklariert werden, sind lokal zur Anweisung.Das Ergebnis dieses Ausdrucks wird verworfen.
condition
Optional-
Ein Ausdruck, der vor jeder Schleifeniteration ausgewertet wird. Wenn dieser Ausdruck zu true ausgewertet wird, wird
statement
ausgeführt. Wenn der Ausdruck zu false ausgewertet wird, wird die Ausführung der Schleife beendet und zur ersten Anweisung nach demfor
-Konstrukt gewechselt.Dieser Bedingungstest ist optional. Wenn er weggelassen wird, wird die Bedingung immer zu true ausgewertet.
afterthought
Optional-
Ein Ausdruck, der am Ende jeder Schleifeniteration ausgewertet wird. Dies geschieht vor der nächsten Auswertung der
condition
. Wird im Allgemeinen verwendet, um die Zählvariable zu aktualisieren oder zu inkrementieren. statement
-
Eine Anweisung, die so lange ausgeführt wird, wie die Bedingung zu true ausgewertet wird. Sie können eine Blockanweisung verwenden, um mehrere Anweisungen auszuführen. Um keine Anweisung innerhalb der Schleife auszuführen, verwenden Sie eine leere Anweisung (
;
).
Beschreibung
Wie bei anderen Schleifenanweisungen können Sie Kontrollflussanweisungen innerhalb von statement
verwenden:
Beispiele
Verwendung von for
Die folgende for
-Anweisung beginnt mit der Deklaration der Variablen i
und ihrer Initialisierung auf 0
. Sie überprüft, ob i
kleiner als neun ist, führt die beiden folgenden Anweisungen aus und inkrementiert i
nach jedem Durchlauf durch die Schleife um 1.
for (let i = 0; i < 9; i++) {
console.log(i);
// more statements
}
Syntax des Initialisierungsblocks
Der Initialisierungsblock akzeptiert sowohl Ausdrücke als auch Variablendeklarationen. Ausdrücke können den in
-Operator jedoch nicht ohne Klammern verwenden, da das mit einer for...in
-Schleife mehrdeutig 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 initializer
for (let i = ("start" in window ? window.start : 0); i < 9; i++) {
console.log(i);
}
// Parenthesize the `in` expression
for (let i = ("start" in window) ? window.start : 0; i < 9; i++) {
console.log(i);
}
Optionale for-Ausdrücke
Alle drei Ausdrücke im Kopf der for
-Schleife sind optional. Zum Beispiel ist es nicht erforderlich, den initialization
-Block zu verwenden, um Variablen zu initialisieren:
let i = 0;
for (; i < 9; i++) {
console.log(i);
// more statements
}
Wie der initialization
-Block ist auch der condition
-Teil optional. Wenn Sie diesen Ausdruck weglassen, müssen Sie sicherstellen, dass Sie die Schleife im Body beenden, 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 wiederum sicher, dass Sie eine break
-Anweisung verwenden, um die Schleife zu beenden, und auch eine Variable ändern (erhöhen), sodass die Bedingung für die break-Anweisung irgendwann wahr ist.
let i = 0;
for (;;) {
if (i > 3) break;
console.log(i);
i++;
}
In Fällen, in denen Sie nicht alle drei Ausdruckspositionen vollständig nutzen — insbesondere wenn Sie keine Variablen mit dem ersten Ausdruck deklarieren, sondern etwas im oberen Gültigkeitsbereich ändern — sollten Sie stattdessen eine while
-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 innerhalb des Initialisierungsblocks unterscheidet sich erheblich von der Deklaration im oberen Gültigkeitsbereich, insbesondere wenn innerhalb des Schleifenbody ein Closure erstellt wird. Zum Beispiel, bei dem folgenden Code:
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
Protokolliert es 0
, 1
und 2
, wie erwartet. Wenn jedoch die Variable im oberen Gültigkeitsbereich definiert ist:
let i = 0;
for (; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
Protokolliert es 3
, 3
und 3
. Der Grund dafür ist, dass jede setTimeout
ein neues Closure erstellt, das die i
-Variable einschließt. Aber wenn i
nicht im Schleifenbody gescoped ist, werden alle Closures auf dieselbe Variable verweisen, wenn sie schließlich aufgerufen werden — und aufgrund der asynchronen Natur von setTimeout()
passiert dies, nachdem die Schleife bereits beendet wurde, was dazu führt, dass der Wert von i
in allen in der Warteschlange stehenden Rückrufkörpern den Wert 3
hat.
Dies passiert auch, wenn Sie eine var
-Anweisung als Initialisierung verwenden, da Variablen, die mit var
deklariert werden, nur funktionsgescoped sind, aber nicht lexikalisch gescoped (d.h. sie können nicht zum Schleifenbody gescopet werden).
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
// Logs 3, 3, 3
Die Scoping-Wirkung des Initialisierungsblocks kann verstanden werden, als ob die Deklaration innerhalb des Schleifenbodys erfolgt, jedoch zufällig innerhalb der condition
- und afterthought
-Teile zugänglich ist. Genauer gesagt, let
-Deklarationen werden von for
-Schleifen speziell behandelt — wenn initialization
eine let
-Deklaration ist, dann geschieht nach jeder Auswertung des Schleifenbodys Folgendes:
- Ein neuer lexikalischer Gültigkeitsbereich wird mit neu
let
-deklarierten Variablen erstellt. - Die Bindungswerte der letzten Iteration werden verwendet, um die neuen Variablen neu zu initialisieren.
afterthought
wird im neuen Gültigkeitsbereich ausgewertet.
Ein neuer lexikalischer Gültigkeitsbereich wird auch nach initialization
erstellt, direkt bevor condition
zum ersten Mal ausgewertet wird. Diese Details können durch das Erstellen von Closures beobachtet werden, die es ermöglichen, eine Bindung zu einem bestimmten Zeitpunkt zu erfassen. Zum Beispiel erfasst ein Closure, das innerhalb des initialization
-Abschnitts erstellt wurde, keine Aktualisierungen von i
im afterthought
:
for (let i = 0, getI = () => i; i < 3; i++) {
console.log(getI());
}
// Logs 0, 0, 0
Dies protokolliert nicht "0, 1, 2", wie es der Fall wäre, wenn getI
im Schleifenbody deklariert ist. Dies liegt daran, dass getI
nicht bei jeder Iteration neu ausgewertet wird — stattdessen wird die Funktion einmal erstellt und schließt die i
-Variable ein, die sich auf die Variable bezieht, die bei der ersten Initialisierung der Schleife deklariert wurde. Nachfolgende Aktualisierungen des i
-Wertes erzeugen tatsächlich neue Variablen namens i
, die getI
nicht sieht. Eine Möglichkeit, dies zu beheben, ist das Neuberechnen von getI
jedes Mal, wenn i
aktualisiert wird:
for (let i = 0, getI = () => i; i < 3; i++, getI = () => i) {
console.log(getI());
}
// Logs 0, 1, 2
Die i
-Variable innerhalb der initialization
ist von der i
-Variable innerhalb jeder Iteration unterschiedlich, einschließlich der ersten. In diesem Beispiel gibt getI
0 zurück, auch wenn der Wert von i
innerhalb der Iteration zuvor erhöht wurde:
for (let i = 0, getI = () => i; i < 3; ) {
i++;
console.log(getI());
}
// Logs 0, 0, 0
Tatsächlich können Sie diese anfängliche Bindung der i
-Variable erfassen und später neu zuweisen, und dieser aktualisierte Wert wird nicht im Schleifenbody sichtbar, der die nächste neue Bindung von i
sieht.
for (
let i = 0, getI = () => i, incrementI = () => i++;
getI() < 3;
incrementI()
) {
console.log(i);
}
// Logs 0, 0, 0
Dies protokolliert "0, 0, 0", weil die i
-Variable in jeder Schleifenbewertung tatsächlich eine separate Variable ist, aber getI
und incrementI
lesen und schreiben beide die anfängliche Bindung von i
, nicht das, was anschließend deklariert wurde.
Verwendung von for ohne Body
Der folgende for
-Zyklus berechnet die Offset-Position eines Knotens im afterthought
-Abschnitt und erfordert daher nicht die Verwendung eines statement
-Abschnitts, 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 der for
-Anweisung obligatorisch ist, da es als leere Anweisung steht. Andernfalls übernimmt die for
-Anweisung die folgende console.log
-Zeile als ihren statement
-Abschnitt, was dazu führt, dass das log
mehrmals ausgeführt wird.
Verwendung von for mit zwei iterierenden Variablen
Sie können zwei Zähler erstellen, die in einer for-Schleife mit dem Komma-Operator gleichzeitig aktualisiert werden. Mehrere let
- und var
-Deklarationen können auch mit Kommas 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 4
Spezifikationen
Specification |
---|
ECMAScript® 2026 Language Specification # sec-for-statement |