@thefourtheye a raison de dire que ces variables ne sont pas accessibles avant d'être déclarées. Cependant, c'est un peu plus compliqué que ça.
Les variables sont-elles déclarées avec let
ou const
non hissées? Que se passe-t-il vraiment ici?
Toutes les déclarations ( var
, let
, const
, function
, function*
, class
) sont "hissés" en JavaScript. Cela signifie que si un nom est déclaré dans une étendue, dans cette étendue, l'identifiant fera toujours référence à cette variable particulière:
x = "global";
// function scope:
(function() {
x; // not "global"
var/let/… x;
}());
// block scope (not for `var`s):
{
x; // not "global"
let/const/… x;
}
Cela est vrai pour les portées de fonction et de bloc 1 .
La différence entre var
/ function
/ function*
déclarations et let
/ const
/ class
déclarations est l' initialisation .
Les premiers sont initialisés avec undefined
ou la fonction (générateur) dès que la liaison est créée en haut de l'étendue. Les variables lexicalement déclarées restent cependant non initialisées . Cela signifie qu'une ReferenceError
exception est levée lorsque vous essayez d'y accéder. Elle ne sera initialisée que lorsque l' instruction let
/ const
/ class
sera évaluée, tout ce qui précède (ci-dessus) est appelé la zone morte temporelle .
x = y = "global";
(function() {
x; // undefined
y; // Reference error: y is not defined
var x = "local";
let y = "local";
}());
Notez qu'une let y;
instruction initialise la variable avec undefined
like let y = undefined;
aurait.
La zone morte temporelle n'est pas un emplacement syntaxique, mais plutôt le temps entre la création de la variable (portée) et l'initialisation. Ce n'est pas une erreur de référencer la variable dans le code au-dessus de la déclaration tant que ce code n'est pas exécuté (par exemple un corps de fonction ou simplement un code mort), et cela lèvera une exception si vous accédez à la variable avant l'initialisation même si l'accès le code est en dessous de la déclaration (par exemple dans une déclaration de fonction hissée appelée trop tôt).
Y a-t-il une différence entre let
et const
dans cette affaire?
Non, ils fonctionnent de la même manière en ce qui concerne le levage. La seule différence entre eux est qu'une const
fourmi doit être et ne peut être affectée que dans la partie initialiseur de la déclaration ( const one = 1;
, les deux const one;
réaffectations et les affectations ultérieures comme ne one = 2
sont pas valides).
1: les var
déclarations ne fonctionnent toujours qu'au niveau de la fonction, bien sûr
let foo = () => bar; let bar = 'bar'; foo();
illustre toutes les déclarations sont effet hissé encore mieux, car ce n'est pas évident en raison de la zone morte temporelle.const
commelet
est un défaut de conception. Dans un périmètre,const
aurait dû être fait pour être hissé et juste-à-temps-initialisé lors de son accès. Vraiment, ils devraient avoir unconst
, unlet
, et un autre mot - clé qui crée une variable qui fonctionne comme une « lecture seule »let
.Citant la spécification ECMAScript 6 (ECMAScript 2015)
let
et laconst
section des déclarations ,Donc, pour répondre à votre question, oui,
let
etconst
hissez, mais vous ne pouvez pas y accéder avant que la déclaration réelle ne soit évaluée au moment de l'exécution.la source
ES6
introduit desLet
variables qui vient avecblock level scoping
. Jusqu'à ce queES5
nous n'en ayons pasblock level scoping
, les variables déclarées dans un bloc sont donc toujourshoisted
fonctionner au niveau de la portée.Scope
Se réfère essentiellement à l'endroit où dans votre programme vos variables sont visibles, ce qui détermine où vous êtes autorisé à utiliser les variables que vous avez déclarées. DansES5
nous avonsglobal scope,function scope and try/catch scope
, avecES6
nous obtenons également la portée au niveau du bloc en utilisant Let.var
mot clé, la fonction entière est connue à partir du moment où elle est définie.Lorsque vous définissez une variable avec une
let
instruction, elle n'est connue que dans le bloc auquel elle est définie.Si vous exécutez le code, vous pouvez voir que la variable
j
est uniquement connue dans leloop
et non avant et après. Pourtant, notre variablei
est connue àentire function
partir du moment où elle est définie.Il y a un autre grand avantage à utiliser let car cela crée un nouvel environnement lexical et lie également une nouvelle valeur plutôt que de conserver une ancienne référence.
La première
for
boucle imprime toujours la dernière valeur, aveclet
elle crée une nouvelle portée et lie les nouvelles valeurs nous imprimant1, 2, 3, 4, 5
.En ce qui concerne
constants
, cela fonctionne essentiellement commelet
, la seule différence est que leur valeur ne peut pas être modifiée. Dans les constantes, la mutation est autorisée mais la réaffectation n'est pas autorisée.Si une constante fait référence à un
object
, elle fera toujours référence auobject
mais leobject
lui - même peut être modifié (s'il est modifiable). Si vous aimez avoir un immuableobject
, vous pouvez utiliserObject.freeze([])
la source
Depuis les documents Web MDN:
Dans ECMAScript 2015,
let
etconst
sont hissés mais pas initialisés. Le fait de référencer la variable dans le bloc avant la déclaration de variable entraîne unReferenceError
car la variable se trouve dans une "zone morte temporelle" depuis le début du bloc jusqu'à ce que la déclaration soit traitée.la source
dans es6 lorsque nous utilisons let ou const, nous devons déclarer la variable avant de les utiliser. par exemple. 1 -
par exemple. 2-
la source