let
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.
Die let
-Deklaration deklariert neu zuweisbare, block-skopierte lokale Variablen und initialisiert diese optional mit einem Wert.
Probieren Sie es aus
let x = 1;
if (x === 1) {
let x = 2;
console.log(x);
// Expected output: 2
}
console.log(x);
// Expected output: 1
Syntax
let name1;
let name1 = value1;
let name1 = value1, name2 = value2;
let name1, name2 = value2;
let name1 = value1, name2, /* …, */ nameN = valueN;
Parameter
nameN
-
Der Name der zu deklarierenden Variablen. Jeder Name muss ein gültiger JavaScript-Bezeichner oder ein Destructuring-Binding-Muster sein.
valueN
Optional-
Der initiale Wert der Variablen. Es kann jeder gültige Ausdruck sein. Der Standardwert ist
undefined
.
Beschreibung
Der Gültigkeitsbereich einer mit let
deklarierten Variablen ist einer der folgenden geschweiften Block-Syntaxen, der die let
-Deklaration am engsten umschließt:
- Block-Statement
switch
-Statementtry...catch
-Statement- Der Body eines eines der
for
-Statements, wenn daslet
im Header des Statements steht - Funktionskörper
- Statischer Initialisierungsblock
Oder falls nichts davon zutrifft:
- Das aktuelle Modul, wenn der Code im Modulmodus ausgeführt wird
- Der globale Gültigkeitsbereich, wenn der Code im Skriptmodus ausgeführt wird.
Im Vergleich zu var
gibt es bei let
-Deklarationen die folgenden Unterschiede:
-
let
-Deklarationen sind sowohl block- als auch funktionsspezifisch. -
let
-Deklarationen können nur nach dem Erreichen der Deklarationsstelle zugegriffen werden (siehe temporal dead zone). Aus diesem Grund werdenlet
-Deklarationen üblicherweise als nicht-hochgehoben angesehen. -
let
-Deklarationen erstellen keine Eigenschaften aufglobalThis
, wenn sie auf oberster Ebene eines Skripts deklariert werden. -
let
-Deklarationen können nicht erneut deklariert werden, weder durch sich selbst noch durch eine andere Deklaration im selben Gültigkeitsbereich. -
let
beginnt Deklarationen, nicht Statements. Das bedeutet, dass eine alleinstehendelet
-Deklaration nicht als Body eines Blocks verwendet werden kann (was Sinn ergibt, da die Variable nicht zugänglich wäre).jsif (true) let a = 1; // SyntaxError: Lexical declaration cannot appear in a single-statement context
Beachten Sie, dass let
als Bezeichnername erlaubt ist, wenn es mit var
oder function
in nicht-striktem Modus deklariert wird. Dennoch sollten Sie vermeiden, let
als Bezeichnernamen zu verwenden, um unerwartete Syntaxzweideutigkeiten zu vermeiden.
Viele Stilrichtlinien (einschließlich derjenigen von MDN) empfehlen die Verwendung von const
statt let
, wenn eine Variable in ihrem Gültigkeitsbereich nicht neu zugewiesen wird. Dies verdeutlicht die Absicht, dass der Typ (oder Wert im Fall eines primitiven Typs) einer Variablen sich niemals ändert. Andere bevorzugen möglicherweise let
für Nicht-Primitivwerte, die mutiert werden.
Die Liste, die auf das Schlüsselwort let
folgt, wird als Binding List bezeichnet und ist durch Kommata getrennt, wobei die Kommata keine Kommaoperatoren und die =
-Zeichen keine Zuweisungsoperatoren sind. Initialisierer späterer Variablen können sich auf frühere Variablen in der Liste beziehen.
Temporale Dead Zone (TDZ)
Eine mit let
, const
oder class
deklarierte Variable befindet sich in einer "temporalen Dead Zone" (TDZ), von Beginn des Blocks bis zur Codeausführung an der Stelle, an der die Variable deklariert und initialisiert wird.
Innerhalb der TDZ wurde der Variablen kein Wert zugewiesen, und jeder Zugriff darauf führt zu einem ReferenceError
. Die Initialisierung erfolgt, wenn der Code die Deklarationsstelle erreicht. Wenn kein Anfangswert angegeben wurde, wird undefined
als Wert zugewiesen.
Dies unterscheidet sich von var
-Variablen, die einen Wert von undefined
zurückgeben, wenn sie vor ihrer Deklaration aufgerufen werden. Der folgende Code demonstriert die unterschiedlichen Ergebnisse beim Zugriff auf let
und var
vor deren Deklaration:
{
// TDZ starts at beginning of scope
console.log(bar); // "undefined"
console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
var bar = 1;
let foo = 2; // End of TDZ (for foo)
}
Der Begriff "tempora" wird verwendet, da die Zone von der Ausführungsreihenfolge (Zeit) und nicht von der Reihenfolge, in der der Code geschrieben ist (Position), abhängt. Zum Beispiel funktioniert der folgende Code, da die Funktion, die die let
-Variable verwendet, außerhalb der TDZ aufgerufen wird, auch wenn sie vor der Variablendeklaration erscheint.
{
// TDZ starts at beginning of scope
const func = () => console.log(letVar); // OK
// Within the TDZ letVar access throws `ReferenceError`
let letVar = 3; // End of TDZ (for letVar)
func(); // Called outside TDZ!
}
Die Verwendung des typeof
-Operators für eine Variable in ihrer TDZ führt zu einem ReferenceError
:
{
typeof i; // ReferenceError: Cannot access 'i' before initialization
let i = 10;
}
Das unterscheidet sich vom Einsatz von typeof
bei nicht deklarierten Variablen und Variablen, die den Wert undefined
enthalten:
console.log(typeof undeclaredVariable); // "undefined"
Note:
let
- undconst
-Deklarationen werden nur verarbeitet, wenn das aktuelle Skript verarbeitet wird. Wenn Sie zwei<script>
-Elemente im Skriptmodus in einem einzigen HTML haben, unterliegt das erste Skript nicht den TDZ-Beschränkungen für Top-Level-let
- oderconst
-Variablen, die im zweiten Skript deklariert wurden. Allerdings führt eine erneute Deklaration einerlet
- oderconst
-Variablen im ersten und im zweiten Skript zu einem Redeclaration Error.
Redeclarations
let
-Deklarationen können nicht im selben Gültigkeitsbereich mit einer anderen Deklaration existieren, einschließlich let
, const
, class
, function
, var
, und import
-Deklarationen.
{
let foo;
let foo; // SyntaxError: Identifier 'foo' has already been declared
}
Eine let
-Deklaration innerhalb eines Funktionskörpers kann nicht denselben Namen haben wie ein Parameter. Auch innerhalb eines catch
-Blocks kann eine let
-Deklaration nicht denselben Namen wie der catch
-gebundene Bezeichner haben.
function foo(a) {
let a = 1; // SyntaxError: Identifier 'a' has already been declared
}
try {
} catch (e) {
let e; // SyntaxError: Identifier 'e' has already been declared
}
Wenn Sie in einer REPL, wie der Firefox-Webkonsole (Tools > Web Developer > Web Console), experimentieren und zwei let
-Deklarationen mit demselben Namen in zwei getrennten Eingaben ausführen, können Sie denselben Redeclarations-Fehler erhalten. Weitere Diskussionen hierzu finden Sie im Firefox-Bug 1580891. Die Chrome-Konsole erlaubt let
-Neudeklarationen zwischen verschiedenen REPL-Eingaben.
In switch
-Statements treten möglicherweise Fehler auf, da es nur einen Block gibt.
let x = 1;
switch (x) {
case 0:
let foo;
break;
case 1:
let foo; // SyntaxError: Identifier 'foo' has already been declared
break;
}
Um den Fehler zu vermeiden, können Sie jeden case
in einen neuen Block einschließen.
let x = 1;
switch (x) {
case 0: {
let foo;
break;
}
case 1: {
let foo;
break;
}
}
Beispiele
Scoping-Regeln
Variablen, die mit let
deklariert wurden, haben ihren Gültigkeitsbereich im Block, für den sie deklariert wurden, sowie in allen enthaltenen Unterblöcken. In dieser Hinsicht funktioniert let
ähnlich wie var
. Der Hauptunterschied ist, dass der Gültigkeitsbereich einer var
-Variablen die gesamte umschließende Funktion ist:
function varTest() {
var x = 1;
{
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
{
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}
Auf der obersten Ebene von Programmen und Funktionen erzeugt let
im Gegensatz zu var
keine Eigenschaft im globalen Objekt. Zum Beispiel:
var x = "global";
let y = "global";
console.log(this.x); // "global"
console.log(this.y); // undefined
TDZ kombiniert mit lexikalischer Sichtbarkeit
Der folgende Code führt zu einem ReferenceError
in der angegebenen Zeile:
function test() {
var foo = 33;
if (foo) {
let foo = foo + 55; // ReferenceError
}
}
test();
Der if
-Block wird ausgewertet, weil die äußere var foo
einen Wert hat. Aufgrund der lexikalischen Sichtbarkeit ist dieser Wert jedoch nicht im Block verfügbar: Der Bezeichner foo
im if
-Block ist das let foo
. Die Anweisung foo + 55
löst einen ReferenceError
aus, da die Initialisierung von let foo
noch nicht abgeschlossen ist — es befindet sich noch in der temporalen Dead Zone.
Dieses Phänomen kann in einer Situation wie der folgenden verwirrend sein. Die Anweisung let n of n.a
befindet sich bereits im Gültigkeitsbereich des Blocks der for...of
-Schleife. Somit wird der Bezeichner n.a
auf die Eigenschaft a
des Objekts n
aufgelöst, das sich im ersten Teil der Anweisung selbst befindet (let n
). Dies befindet sich jedoch immer noch in der temporalen Dead Zone, da die Deklarationsanweisung noch nicht erreicht und abgeschlossen wurde.
function go(n) {
// n here is defined!
console.log(n); // { a: [1, 2, 3] }
for (let n of n.a) {
// ^ ReferenceError
console.log(n);
}
}
go({ a: [1, 2, 3] });
Andere Situationen
Wenn let
innerhalb eines Blocks verwendet wird, begrenzt es den Gültigkeitsbereich der Variablen auf diesen Block. Beachten Sie den Unterschied zu var
, dessen Gültigkeitsbereich innerhalb der Funktion liegt, in der es deklariert wird:
var a = 1;
var b = 2;
{
var a = 11; // the scope is global
let b = 22; // the scope is inside the block
console.log(a); // 11
console.log(b); // 22
}
console.log(a); // 11
console.log(b); // 2
Die folgende Kombination aus var
- und let
-Deklarationen führt jedoch zu einem SyntaxError
, da var
nicht blockskopiert ist, was dazu führt, dass beide Deklarationen im selben Gültigkeitsbereich liegen. Dies resultiert in einer impliziten Neudeklaration der Variablen.
let x = 1;
{
var x = 2; // SyntaxError for re-declaration
}
Deklaration mit Destructuring
Die linke Seite jedes =
kann auch ein Binding-Muster sein. Dies ermöglicht das Erstellen mehrerer Variablen auf einmal.
const result = /(a+)(b+)(c+)/.exec("aaabcc");
let [, a, b, c] = result;
console.log(a, b, c); // "aaa" "b" "cc"
Weitere Informationen finden Sie unter Destructuring-Zuweisung.
Spezifikationen
Specification |
---|
ECMAScript® 2025 Language Specification # sec-let-and-const-declarations |
Browser-Kompatibilität
Report problems with this compatibility data on GitHubdesktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
let |
Legend
Tip: you can click/tap on a cell for more information.
- Full support
- Full support
- Partial support
- Partial support
- See implementation notes.
- Has more compatibility info.
Siehe auch
var
const
- Hoisting
- ES6 In Depth:
let
andconst
auf hacks.mozilla.org (2015) - Breaking changes in
let
andconst
in Firefox 44 auf blog.mozilla.org (2015) - You Don't Know JS: Scope & Closures, Ch.3: Function vs. Block Scope von Kyle Simpson
- What is the Temporal Dead Zone? auf Stack Overflow
- Was ist der Unterschied zwischen der Verwendung von
let
undvar
? auf Stack Overflow - Warum wurde der Name 'let' für block-skopierte Variablendeklarationen in JavaScript gewählt? auf Stack Overflow