@thefourtheye sagt zu Recht, dass auf diese Variablen nicht zugegriffen werden kann, bevor sie deklariert wurden. Es ist jedoch etwas komplizierter.
Werden Variablen mit deklariert let
oder const
nicht gehisst? Was ist hier wirklich los?
Alle Erklärungen ( var
, let
, const
, function
, function*
, class
) werden als "hochgezogen" in JavaScript. Dies bedeutet, dass, wenn ein Name in einem Bereich deklariert ist, der Bezeichner in diesem Bereich immer auf diese bestimmte Variable verweist:
x = "global";
// function scope:
(function() {
x; // not "global"
var/let/… x;
}());
// block scope (not for `var`s):
{
x; // not "global"
let/const/… x;
}
Dies gilt sowohl für Funktions- als auch für Blockbereiche 1 .
Der Unterschied zwischen var
/ function
/ function*
Deklarationen und let
/ const
/ class
Deklarationen ist die Initialisierung .
Erstere werden mit undefined
oder mit der (Generator-) Funktion initialisiert, sobald die Bindung oben im Bereich erstellt wird. Die lexikalisch deklarierten Variablen bleiben jedoch nicht initialisiert . Dies bedeutet, dass eine ReferenceError
Ausnahme ausgelöst wird, wenn Sie versuchen, darauf zuzugreifen. Es wird nur initialisiert, wenn die let
/ const
/ class
-Anweisung ausgewertet wird, alles vor (oben), was als zeitliche Totzone bezeichnet wird .
x = y = "global";
(function() {
x; // undefined
y; // Reference error: y is not defined
var x = "local";
let y = "local";
}());
Beachten Sie, dass eine let y;
Anweisung die Variable mit undefined
like initialisiert let y = undefined;
.
Die zeitliche Totzone ist kein syntaktischer Ort, sondern die Zeit zwischen der Erstellung der Variablen (Bereich) und der Initialisierung. Es ist kein Fehler, auf die Variable im Code über der Deklaration zu verweisen, solange dieser Code nicht ausgeführt wird (z. B. ein Funktionskörper oder einfach toter Code), und es wird eine Ausnahme ausgelöst, wenn Sie vor der Initialisierung auf die Variable zugreifen, auch wenn der Zugriff erfolgt Code befindet sich unterhalb der Deklaration (z. B. in einer zu früh aufgerufenen angehobenen Funktionsdeklaration).
Gibt es einen Unterschied zwischen let
und const
in dieser Angelegenheit?
Nein, sie funktionieren genauso, was das Heben betrifft. Der einzige Unterschied zwischen ihnen besteht darin, dass eine const
Ameise nur im Initialisierungsteil der Deklaration zugewiesen werden muss und kann ( const one = 1;
beide const one;
und spätere Neuzuweisungen wie one = 2
sind ungültig).
1: var
Deklarationen funktionieren natürlich immer noch nur auf Funktionsebene
let foo = () => bar; let bar = 'bar'; foo();
illustriert, dass alle Deklarationen noch besser gehisst werden , weil es aufgrund der zeitlichen Totzone nicht offensichtlich ist.const
wie zu machen,let
ist ein Designfehler. Innerhalb eines Bereichsconst
sollte dafür gesorgt werden, dass er beim Zugriff angehoben und just-in-time-initialisiert wird. Eigentlich sollten sie einconst
, einlet
und ein anderes Schlüsselwort haben, das eine Variable erstellt, die wie "schreibgeschützt" funktioniertlet
.Zitieren der Spezifikationen von ECMAScript 6 (ECMAScript 2015)
let
undconst
Erklärungen zu ,Um Ihre Frage zu beantworten, ja,
let
undconst
heben Sie, aber Sie können nicht darauf zugreifen, bevor die tatsächliche Deklaration zur Laufzeit ausgewertet wird.quelle
ES6
führtLet
Variablen ein, die mit kommenblock level scoping
. BisES5
wir nicht hattenblock level scoping
, also sind die Variablen, die innerhalb eines Blocks deklariert werden, immerhoisted
auf Funktionsebene Scoping.Scope
Bezieht sich im Wesentlichen darauf, wo in Ihrem Programm Ihre Variablen sichtbar sind, wodurch bestimmt wird, wo Sie von Ihnen deklarierte Variablen verwenden dürfen. In habenES5
wirglobal scope,function scope and try/catch scope
, mit bekommenES6
wir auch das Block-Level-Scoping mit Let.var
Schlüsselwort definieren, ist die gesamte Funktion vom Moment ihrer Definition an bekannt.Wenn Sie eine Variable mit
let
Anweisung definieren, ist sie nur in dem Block bekannt, in dem sie definiert ist.Wenn Sie den Code ausführen, können Sie sehen, dass die Variable
j
nur imloop
und nicht vorher und nachher bekannt ist. Unsere Variablei
ist jedoch in der bekanntentire function
ab dem Zeitpunkt ihrer Definition bekannt.Es gibt einen weiteren großen Vorteil bei der Verwendung von let, da es eine neue lexikalische Umgebung schafft und auch neuen Wert bindet, anstatt eine alte Referenz beizubehalten.
Die erste
for
Schleife druckt immer den letzten Wert,let
erstellt einen neuen Bereich und bindet neue Werte, die uns drucken1, 2, 3, 4, 5
.Kommen zu
constants
, es funktioniert im Grunde wielet
, ist der einzige Unterschied ihr Wert kann nicht geändert werden. In Konstanten ist eine Mutation zulässig, eine Neuzuweisung jedoch nicht.Wenn sich eine Konstante auf eine bezieht, bezieht
object
sie sich immer auf die,object
aber dieobject
selbst kann geändert werden (wenn sie veränderbar ist). Wenn Sie eine unveränderliche haben möchtenobject
, können Sie verwendenObject.freeze([])
quelle
Aus MDN-Webdokumenten:
In ECMAScript 2015
let
undconst
werden gehisst, aber nicht initialisiert. Das Verweisen auf die Variable im Block vor der Variablendeklaration führt zu a,ReferenceError
da sich die Variable vom Beginn des Blocks bis zur Verarbeitung der Deklaration in einer "zeitlichen Totzone" befindet.quelle
Wenn wir in es6 let oder const verwenden, müssen wir die Variable deklarieren, bevor wir sie verwenden. z.B. 1 -
z.B. 2-
quelle