Qual è la zona morta temporale?


150

Ho sentito che l'accesso lete i constvalori prima che vengano inizializzati possono causare a ReferenceErrorcausa di qualcosa chiamato zona morta temporale .

Qual è la zona morta temporale, in che modo si collega all'ambito e al sollevamento e in quali situazioni si trova?


6
possibile duplicato di Le variabili sono dichiarate con let o const non issate in ES6? - sebbene la domanda non si concentri sul TDZ, le risposte sono sostanzialmente le stesse
Bergi,

Risposte:


201

lete consthanno due grandi differenze rispetto a var:

  1. Sono con ambito di blocco .
  2. Accedere a varprima che venga dichiarato ha il risultato undefined; accedendo a leto constprima che venga dichiarato lancio ReferenceError:

console.log(aVar); // undefined
console.log(aLet); // causes ReferenceError: aLet is not defined
var aVar = 1;
let aLet = 2;

Da questi esempi risulta che le letdichiarazioni (e constche funzionano allo stesso modo) non possono essere sollevate , poiché aLetnon sembrano esistere prima che gli venga assegnato un valore.

Questo non è il caso, tuttavia- lete const sono issato (come var, classe function), ma v'è un periodo tra un'entrata portata e di essere dichiarato in cui non è possibile accedere. Questo periodo è la zona morta temporale (TDZ) .

Il TDZ termina quando aLetviene dichiarato , anziché assegnato :

//console.log(aLet)  // would throw ReferenceError

let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10

Questo esempio mostra che letè stato sollevato:

let x = 'outer value';
(function() {
  // start TDZ for x
  console.log(x);
  let x = 'inner value'; // declaration ends TDZ for x
}());

Ringraziamento: Temporal Dead Zone (TDZ) demistificato

L'accesso xnell'ambito interno causa ancora a ReferenceError. Se letnon fosse stato sollevato, si registrava outer value.

Il TDZ è positivo perché aiuta a evidenziare i bug: l'accesso a un valore prima che sia stato dichiarato è raramente intenzionale.

Il TDZ si applica anche agli argomenti di funzione predefiniti. Gli argomenti vengono valutati da sinistra a destra e ogni argomento si trova nel TDZ fino a quando non viene assegnato:

// 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.

TDZ non è abilitato per impostazione predefinita nel transpiler babel.js. Attiva la modalità "alta conformità" per utilizzarlo nella REPL . Fornire il es6.spec.blockScopingflag per usarlo con l'interfaccia della riga di comando o come libreria.

Ulteriori letture consigliate: TDZ demistificato e ES6 Let, Const e la "Zona morta temporale" (TDZ) in profondità .



@zeroflagL buon collegamento, grazie. Inoltre dice: "foo non è dichiarato, è non inizializzato", che il linguaggio sarebbe utile per chiarire / correggere nella risposta sopra. let fooin un blocco fa sì che venga sollevato e dichiarato in cima a quel blocco. La linea di let foocausa lo inizializza. E foo = xyzfa sì che gli venga assegnato un valore.
AJP,

2
Penso che questo sia un ottimo post! Tuttavia, avevo l'impressione che "let" non fosse soggetto a sollevamento? Ho trovato questo nei documenti di Mozilla: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Non sto cercando di fare il curmudgeon, ero solo curioso e sono aperto al chiarimento.
dmarges,

1
@jeows La pagina MDN dice ancora che non sono stati sollevati. Dovresti provare a modificarlo, se sei veramente sicuro di quello che stai dicendo. Penso che dovrei pubblicare una domanda al riguardo.
doubleOrt

1
@joews IMO, potresti dire che sono stati sollevati ma non è possibile accedervi prima che la loro dichiarazione sia raggiunta a causa del TDZ, oppure potresti dire che non sono stati sollevati ma il TDZ provocherà un riferimento a loro. In pratica, entrambe le affermazioni sono ugualmente vere. Tranne, credo, stai usando il termine "sollevamento" in senso astratto, come in "sollevamento = ogni volta che il motore è a conoscenza dell'esistenza di quella variabile". È per questo? Inoltre, cosa dicono le specifiche al riguardo?
doubleOrt

7

Sollevamento:
let , const, varsono tutti get processo issato.
(il che significa che vanno in alto e dichiarano in cima all'ambito.)

Inizializzazione:

  • varpassare anche attraverso il processo iniziale e ottenere il valore iniziale di undefined.
  • mentre let, constnon è stato lanciato il processo iniziale, quindi i loro valori sono ancora inaccessibili, sebbene abbiano già dichiarato. cosa li ha messi dentrotemporal dead zone

Quindi in breve:

processo di sollevamento: var, let, const
Processo d'inizializzazione: var


0

Nel caso di variabili let e const, Fondamentalmente, Dead Zone temporale è una zona

"prima che la tua variabile venga dichiarata",

cioè dove non è possibile accedere al valore di queste variabili, verrà generato un errore.

ex.

let sum = a + 5;        //---------
//some other code       //         | ------>  this is TDZ for variable a
                        //         |
console.log(sum)        //---------
let a = 5;

sopra il codice dà un errore

lo stesso codice non genererà un errore quando utilizziamo var per la variabile "a",

ex.

var sum = a;                            
console.log(sum)     //prints undefined
var a = 5;

il log della console produce "NaN" nel secondo esempio (il risultato dell'aggiunta di undefinede 5). La dichiarazione di var aviene sollevata, il codice di inifializzazione impostato asu 5 non lo è.
traktor53,

sì, giusto, a viene sollevato senza alcuna inizializzazione. Quindi una volontà non sarà definita.
niranjan harpale,

Il primo esempio citato non è corretto, correggilo o rimuovilo.
Spidi's Web
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.