J'ai entendu dire qu'accéder aux valeurs let
et const
avant leur initialisation peut provoquer un ReferenceError
à cause de ce qu'on appelle zone morte temporelle.
Qu'est-ce que la zone morte temporelle, en quoi est-elle liée à la portée et au levage, et dans quelles situations est-elle rencontrée?
let
et const
ont deux grandes différences par rapport à var
:
var
avant sa déclaration a pour résultat undefined
; accéder à un let
ou const
avant qu'il ne soit déclaré jette ReferenceError
:console.log(aVar); // undefined
console.log(aLet); // causes ReferenceError: aLet is not defined
var aVar = 1;
let aLet = 2;
Il ressort de ces exemples que let
déclarations (et const
, qui fonctionne de la même manière) peuvent ne pas être levé , puisque aLet
n'apparaît pas d'exister avant qu'une valeur ne lui soit affectée.
Ce n'est cependant pas le cas — let
et const
sont hissé (comme var
, class
et function
), mais il y a un délai entre l'entrée dans la portée et la déclaration où il est impossible d'y accéder. Cette période est la zone morte temporelle (TDZ) .
Le TDZ se termine lorsque aLet
est déclaré, plutôt que assigné:
//console.log(aLet) // would throw ReferenceError
let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10
Cet exemple montre que let
est levé:
let x = 'outer value';
(function() {
// start TDZ for x
console.log(x);
let x = 'inner value'; // declaration ends TDZ for x
}());
Crédit: La zone morte temporelle (TDZ) démystifiée
L'accès à x
dans la portée interne provoque toujours un ReferenceError
. Si let
n'était pas levé, il s'enregistrerait outer value
.
Le TDZ est une bonne chose, car il permet de mettre en évidence les bugs: accéder à une valeur avant qu’elle ait été déclarée est rarement intentionnelle.
Le TDZ s'applique également aux arguments de fonction par défaut. Les arguments sont évalués de gauche à droite et chaque argument est dans le TDZ jusqu'à ce qu'il soit affecté:
// b is in TDZ until its value is assigned
function testDefaults(a=b, b) { }
testDefaults(undefined, 1); // throws ReferenceError because the evaluation of a reads b before it has been evaluated.
Le TDZ n'est pas activé par défaut dans le transpiler babel.js . Activez le mode "conformité élevée" pour l’utiliser dans le REPL . Fournir le es6.spec.blockScoping
drapeau pour l’utiliser avec la CLI ou comme bibliothèque.
Autres lectures recommandées: TDZ démystifié et ES6 Let, Const et la "Zone morte temporelle" (TDZ) en profondeur .
Levage:let
, const
, var
obtiennent tous le processus hissé.
(Qu'est-ce qui signifie qu'ils vont en haut et se déclarent en haut de la portée?)
Initialisation:
var
va également lancer le processus initial et obtenir la valeur initiale de undefined
.let
, const
ne soit pas passé par le processus initial, leurs valeurs sont toujours inaccessibles, bien qu’elles aient déjà été déclarées. ce qui les met dans temporal dead zone
donc dans peu de temps:
processus de levage:
var
,let
,const
Processus d’initialisation:var
En cas de variables let et const, fondamentalement, la zone morte temporelle est une zone
"avant que votre variable soit déclarée",
si vous ne pouvez pas accéder à la valeur de ces variables, une erreur sera générée.
ex.
let sum = a + 5; //---------
//some other code // | ------> this is TDZ for variable a
// |
console.log(sum) //---------
let a = 5;
le code ci-dessus donne une erreur
le même code ne donnera pas d'erreur quand on utilise var pour la variable 'a',
ex.
let sum = a + 5;
console.log(sum) //prints 10
var a = 5;