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 (meistens einer Blockanweisung), die in der Schleife ausgeführt wird.
Probieren Sie es aus
let str = "";
for (let i = 0; i < 9; i++) {
str = str + i;
}
console.log(str);
// Expected output: "012345678"
Syntax
for (initialization; condition; afterthought)
statement
initialization
Optional-
Ein Ausdruck (einschließlich Zuweisungsausdrücke) oder Variablendeklaration, die einmal vor Beginn der Schleife ausgewertet wird. Typischerweise verwendet, um eine Zählvariabel zu initialisieren. Dieser Ausdruck kann optional neue Variablen mit den Schlüsselwörtern
var
oderlet
deklarieren. Variablen, die mitvar
deklariert werden, sind nicht lokal für die Schleife, das heißt, sie befinden sich im selben Gültigkeitsbereich, in dem sich diefor
-Schleife befindet. Variablen, die mitlet
deklariert werden, sind lokal für die Anweisung.Das Ergebnis dieses Ausdrucks wird verworfen.
condition
Optional-
Ein Ausdruck, der vor jeder Iteration der Schleife ausgewertet wird. Wenn dieser Ausdruck wahr ergibt, wird
statement
ausgeführt. Wenn der Ausdruck falsch ergibt, wird die Ausführung beendet und geht zur ersten Anweisung nach demfor
-Konstrukt.Dieser bedingte Test ist optional. Wenn weggelassen, ergibt die Bedingung immer wahr.
afterthought
Optional-
Ein Ausdruck, der am Ende jeder Schleifeniteration ausgewertet wird. Dies geschieht vor der nächsten Bewertung von
condition
. In der Regel verwendet, um die Zählvariabel zu aktualisieren oder zu inkrementieren. statement
-
Eine Anweisung, die solange ausgeführt wird, wie die Bedingung als wahr 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 innerhalb von statement
Kontrollflussanweisungen verwenden:
Beispiele
Verwendung von for
Die folgende for
-Anweisung beginnt mit der Deklaration der Variablen i
und deren Initialisierung auf 0
. Sie überprüft, ob i
kleiner als neun ist, führt die beiden nachfolgenden Anweisungen aus und inkrementiert i
um 1 nach jedem Durchlauf durch die 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 den in
-Operator ohne Klammern verwenden, da dies 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 Körper abbrechen, um keine Endlosschleife zu erstellen.
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 eine break
-Anweisung verwenden, um die Schleife zu beenden, und auch eine Variable modifizieren (erhöhen), sodass die Bedingung für die break-Anweisung zu einem bestimmten Zeitpunkt wahr ist.
let i = 0;
for (;;) {
if (i > 3) break;
console.log(i);
i++;
}
Wenn Sie jedoch nicht alle drei Ausdruckspositionen vollständig nutzen — insbesondere, wenn Sie keine Variablen mit dem ersten Ausdruck deklarieren, sondern etwas im oberen Bereich mutieren — 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
Die Deklaration einer Variablen innerhalb des Initialisierungsblocks weist wichtige Unterschiede zur Deklaration im oberen Gültigkeitsbereich auf, insbesondere bei der Erstellung eines Closures im Schleifenrumpf. Beispielsweise für den folgenden Code:
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
Es protokolliert 0
, 1
und 2
, wie erwartet. Wenn die Variable jedoch im oberen Gültigkeitsbereich definiert ist:
let i = 0;
for (; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
Es protokolliert 3
, 3
und 3
. Der Grund dafür ist, dass jede setTimeout
ein neues Closure erstellt, das über die i
-Variable geschlossen wird. Aber wenn i
nicht in den Schleifenrumpf eingebunden ist, verweisen alle Closures auf dieselbe Variable, wenn sie schließlich aufgerufen werden — und aufgrund der asynchronen Natur von setTimeout()
geschieht dies, nachdem die Schleife bereits beendet ist, was dazu führt, dass der Wert von i
in den Körpern aller in die Warteschlange gestellten Rückrufe den Wert 3
hat.
Dies geschieht auch, wenn Sie eine var
-Anweisung für die Initialisierung verwenden, da Variablen, die mit var
deklariert werden, nur funktionsübergreifend, aber nicht lexikalisch im Bereich sind (d.h. sie können nicht auf den Schleifenrumpf beschränkt werden).
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
// Logs 3, 3, 3
Der Bereichseffekt des Initialisierungsblocks kann so verstanden werden, als ob die Deklaration innerhalb des Schleifenrumpfs erfolgt, aber 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 passiert jedes Mal, nachdem der Schleifenrumpf ausgewertet wurde, 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.
afterthought
wird im neuen Bereich ausgewertet.
Das erneute Zuweisen der neuen Variablen innerhalb von afterthought
beeinflusst nicht die Bindungen aus der vorherigen Iteration.
Ein neuer lexikalischer Bereich wird auch nach initialization
erstellt, bevor condition
zum ersten Mal ausgewertet wird. Diese Details können durch die Erstellung von Closures beobachtet werden, die es ermöglichen, eine Bindung zu einem bestimmten Zeitpunkt zu erfassen. Zum Beispiel in diesem Code wird ein Closure, das im initialization
-Abschnitt erstellt wurde, nicht durch Neu-Zuweisungen von i
im afterthought
aktualisiert:
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 Schleifenrumpf deklariert wird. Dies liegt daran, dass getI
nicht bei jeder Iteration neu ausgewertet wird — vielmehr wird die Funktion einmal erstellt und schließt über die i
-Variable, die sich auf die Variable bezieht, die deklariert wurde, als die Schleife zuerst initialisiert wurde. Nachfolgende Aktualisierungen des Werts von i
erstellen tatsächlich neue Variablen namens i
, die getI
nicht sieht. Eine Möglichkeit, dies zu beheben, besteht darin, getI
jedes Mal neu zu berechnen, 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, einschließlich der ersten, verschieden. Also gibt in diesem Beispiel getI
0 zurück, obwohl der Wert von i
innerhalb der Iteration vorher erhöht wird:
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 für den Schleifenrumpf 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 bei jeder Schleifenbewertung tatsächlich eine separate Variable ist, aber getI
und incrementI
lesen und schreiben die anfängliche Bindung von i
, nicht das, was anschließend deklariert wurde.
Verwendung von for ohne Körper
Die folgende for
-Schleife berechnet die Offset-Position eines Knotens im afterthought
-Abschnitt, und daher ist die Verwendung eines statement
-Abschnitts nicht erforderlich, es wird stattdessen 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, wodurch das log
mehrfach ausgeführt wird.
Verwendung von for mit zwei iterierenden Variablen
Sie können zwei Zähler erstellen, die gleichzeitig in einer for-Schleife mit dem Komma-Operator 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® 2025 Language Specification # sec-for-statement |
Browser-Kompatibilität
BCD tables only load in the browser