Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.
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.
Dielet-Deklaration deklariert erneut zuweisbare, block-skopierte lokale Variablen und initialisiert diese optional mit einem Wert.
In diesem Artikel
Probieren Sie es aus
let x = 1;if (x === 1) { let x = 2; console.log(x); // Expected output: 2}console.log(x);// Expected output: 1Syntax
let name1;let name1 = value1;let name1 = value1, name2 = value2;let name1, name2 = value2;let name1 = value1, name2, /* …, */ nameN = valueN;Parameter
nameNDer Name der zu deklarierenden Variablen. Jeder muss ein gültiger JavaScript-Bezeichner oder einDestrukturierungsmuster sein.
valueNOptionalAnfangswert der Variablen. Es kann jeder gültige Ausdruck sein. Der Standardwert ist
undefined.
Beschreibung
Der Gültigkeitsbereich einer mitlet deklarierten Variablen ist eine der folgenden geschweiften Klammern umschließenden Syntaxen, die am engsten dielet-Deklaration umfasst:
- Block-Anweisung
switch-Anweisungtry...catch-Anweisung- Körper einereiner der
for-Anweisungen, wenn sich dasletin der Kopfleiste der Anweisung befindet - Funktionskörper
- Statischer Initialisierungsblock
Oder wenn keine der oben genannten zutrifft:
- Das aktuelleModul für Code, der im Modulmodus ausgeführt wird
- Der globale Gültigkeitsbereich für Code, der im Skriptmodus ausgeführt wird.
Im Vergleich zuvar habenlet-Deklarationen die folgenden Unterschiede:
let-Deklarationen sind sowohl für Blöcke als auch für Funktionen skopiert.let-Deklarationen können nur nach Erreichen des Deklarationsorts zugegriffen werden (siehetemporal dead zone). Aus diesem Grund werdenlet-Deklarationen häufig alsnicht-hoisted angesehen.let-Deklarationen erstellen keine Eigenschaften aufglobalThis, wenn sie auf der obersten Ebene eines Skripts deklariert werden.let-Deklarationen können im selben Gültigkeitsbereich von keiner anderen Deklarationneu deklariert werden.letbeginntDeklarationen, nichtAnweisungen. Das bedeutet, dass Sie keine alleinstehendelet-Deklaration als den Körper eines Blocks verwenden können (was sinnvoll ist, da es keine Möglichkeit gibt, auf die Variable zuzugreifen).jsif (true) let a = 1; // SyntaxError: Lexical declaration cannot appear in a single-statement context
Beachten Sie, dasslet als Bezeichnername erlaubt ist, wenn es mitvar oderfunction imNicht-Strikt-Modus deklariert wird. Es wird jedoch empfohlen, die Verwendung vonlet als Bezeichnername zu vermeiden, um unerwartete Syntaxmehrdeutigkeiten zu verhindern.
Viele Stilrichtlinien (einschließlichMDNs) empfehlen die Verwendung vonconst überlet, wann immer eine Variable in ihrem Gültigkeitsbereich nicht neu zugewiesen wird. Dies macht die Absicht deutlich, dass sich der Typ (oder Wert, im Falle eines primitiven Typs) einer Variablen niemals ändern kann. Andere bevorzugen möglicherweiselet für nicht-primitive Typen, die verändert werden.
Die Liste, die demlet-Schlüsselwort folgt, wirdBinding-Liste genannt und wird durch Kommas getrennt, wobei die KommaskeineKommaoperatoren und die=-ZeichenkeineZuweisungsoperatoren sind. Initialisierer späterer Variablen können sich auf frühere Variablen in der Liste beziehen.
Zeitliche tote Zone (TDZ)
Eine mitlet,const oderclass deklarierte Variable befindet sich in einer "zeitlichen toten Zone" (TDZ) von Beginn des Blocks bis die Codeausführung die Stelle erreicht, an der die Variable deklariert und initialisiert wird.
Während sie sich in der TDZ befindet, wurde die Variable nicht mit einem Wert initialisiert, und jeder Versuch, darauf zuzugreifen, führt zu einemReferenceError. Die Variable wird mit einem Wert initialisiert, wenn die Ausführung die Stelle im Code erreicht, an der sie deklariert wurde. Wenn mit der Variablendeklaration kein Anfangswert angegeben wurde, wird sie mit einem Wert vonundefined initialisiert.
Dies unterscheidet sich vonvar-Variablen, die einen Wert vonundefined zurückgeben, wenn auf sie zugegriffen wird, bevor sie deklariert werden. Der folgende Code zeigt das unterschiedliche Ergebnis, wennlet undvar im Code verwendet werden, bevor sie deklariert werden.
{ // 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 "zeitlich" wird verwendet, weil die Zone von der Reihenfolge der Ausführung (Zeit) abhängt und nicht von der Reihenfolge, in der der Code geschrieben ist (Position). Zum Beispiel funktioniert der folgende Code, obwohl die Funktion, die dielet-Variable verwendet, vor der Deklaration der Variable erscheint, weil die Funktionaußerhalb der TDZaufgerufen wird.
{ // 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 destypeof-Operators für eine Variable in ihrer TDZ führt zu einemReferenceError:
{ typeof i; // ReferenceError: Cannot access 'i' before initialization let i = 10;}Dies unterscheidet sich von der Verwendung vontypeof für nicht deklarierte Variablen und Variablen, die den Wertundefined enthalten:
console.log(typeof undeclaredVariable); // "undefined"Hinweis:let- undconst-Deklarationen werden nur verarbeitet, wenn das aktuelle Skript verarbeitet wird. Wenn Sie zwei<script>-Elemente im Skriptmodus innerhalb eines HTML ausführen, unterliegt das erste Skript nicht den TDZ-Einschränkungen fürlet- oderconst-Variablen auf oberster Ebene, die im zweiten Skript deklariert wurden. Wenn Sie jedoch einelet- oderconst-Variable im ersten Skript deklarieren, führt ihre erneute Deklaration im zweiten Skript zu einemNeudeklarationsfehler.
Neudeklarationen
let-Deklarationen dürfen sich nicht im selben Gültigkeitsbereich wie jede andere Deklaration befinden, einschließlichlet,const,class,function,var undimport-Deklarationen.
{ let foo; let foo; // SyntaxError: Identifier 'foo' has already been declared}Einelet-Deklaration innerhalb des Funktionskörpers darf nicht denselben Namen wie ein Parameter haben. Einelet-Deklaration innerhalb einescatch-Blocks darf nicht denselben Namen wie dercatch-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 einem REPL experimentieren, wie z.B. der Firefox-Webkonsole (Tools >Web Developer >Web Console), und Sie führen zweilet-Deklarationen mit demselben Namen in zwei separaten Eingaben aus, können Sie denselben Neudeklarationsfehler erhalten. Eine weitere Diskussion dieses Problems finden Sie unterFirefox-Bug 1580891. Die Chrome-Konsole erlaubtlet-Neudeklarationen zwischen unterschiedlichen REPL-Eingaben.
Sie können auf Fehler inswitch-Anweisungen stoßen, weil 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, umschließen Sie jedencase in einer neuen Blockanweisung.
let x = 1;switch (x) { case 0: { let foo; break; } case 1: { let foo; break; }}Beispiele
>Gültigkeitsbereichsregeln
Variablen, die mitlet deklariert werden, haben ihren Gültigkeitsbereich im Block, für den sie deklariert werden, sowie in allen enthaltenen Unterblöcken. Auf diese Weise funktioniertlet sehr ähnlich wievar. Der Hauptunterschied ist, dass der Gültigkeitsbereich einervar-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 erstelltlet, im Gegensatz zuvar, keine Eigenschaft im globalen Objekt. Zum Beispiel:
var x = "global";let y = "global";console.log(this.x); // "global"console.log(this.y); // undefinedTDZ kombiniert mit lexikalischem Gültigkeitsbereich
Der folgende Code führt zu einemReferenceError in der gezeigten Zeile:
function test() { var foo = 33; if (foo) { let foo = foo + 55; // ReferenceError }}test();Derif-Block wird ausgewertet, weil die äußerevar foo einen Wert hat. Aufgrund des lexikalischen Gültigkeitsbereichs ist dieser Wert jedoch im Block nicht verfügbar: Der Bezeichnerfooinnerhalb desif-Blocks ist daslet foo. Der Ausdruckfoo + 55 wirft einenReferenceError, weil die Initialisierung vonlet foo nicht abgeschlossen ist — es befindet sich noch in der zeitlichen toten Zone.
Dieses Phänomen kann in einer Situation wie der folgenden verwirrend sein. Die Anweisunglet n of n.a befindet sich bereits im Gültigkeitsbereich des Blockes derfor...of-Schleife. Somit wird der Bezeichnern.a auf die Eigenschafta desn-Objektes im ersten Teil der Anweisung selbst (let n) aufgelöst. Dies ist immer noch in der zeitlichen toten Zone, da die Deklarationsanweisung nicht erreicht und abgeschlossen ist.
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
Wennlet innerhalb eines Blocks verwendet wird, beschränkt es den Gültigkeitsbereich der Variablen auf diesen Block. Beachten Sie den Unterschied zuvar, dessen Gültigkeitsbereich innerhalb der Funktion liegt, in der es deklariert ist.
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); // 11console.log(b); // 2Diese Kombination ausvar- undlet-Deklarationen unten ist jedoch einSyntaxError, weilvar nicht blockskopiert ist und sie so im selben Gültigkeitsbereich sind. Dies führt zu einer impliziten Neudeklaration der Variablen.
let x = 1;{ var x = 2; // SyntaxError for re-declaration}Deklaration mit Destrukturierung
Die linke Seite jedes= kann auch ein Bindungsmuster sein. Dies ermöglicht die Erstellung mehrerer Variablen gleichzeitig.
const result = /(a+)(b+)(c+)/.exec("aaabcc");let [, a, b, c] = result;console.log(a, b, c); // "aaa" "b" "cc"Für weitere Informationen sieheDestrukturierung.
Spezifikationen
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-let-and-const-declarations> |
Browser-Kompatibilität
Siehe auch
varconst- Hoisting
- ES6 In Depth:
letandconstauf hacks.mozilla.org (2015) - Breaking changes in
letandconstin 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
- What is the difference between using
letandvar? auf Stack Overflow - Why was the name 'let' chosen for block-scoped variable declarations in JavaScript? auf Stack Overflow