Was ist die zeitliche Totzone?

150

Ich habe gehört, dass der Zugriff letund die constWerte vor der Initialisierung ReferenceErroraufgrund der sogenannten zeitlichen Totzone eine Ursache sein können .

Was ist die zeitliche Totzone, in welcher Beziehung steht sie zu Umfang und Heben und in welchen Situationen ist sie anzutreffen?

Joews
quelle
6
Mögliches Duplikat von Werden Variablen, die mit let oder const deklariert wurden, in ES6 nicht angehoben? - Obwohl sich die Frage nicht auf die TDZ konzentriert, sind die Antworten im Grunde die gleichen
Bergi

Antworten:

201

letund consthaben zwei große Unterschiede von var:

  1. Sie haben einen Blockumfang .
  2. Der Zugriff auf a, varbevor es deklariert wird, hat das Ergebnis undefined; Zugriff auf ein letoder constbevor es deklariert wird wirft ReferenceError:

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

Aus diesen Beispielen geht hervor, dass letDeklarationen (und const, die auf die gleiche Weise funktionieren) möglicherweise nicht gehisst werden , da aLetsie nicht zu existieren scheinen, bevor ihr ein Wert zugewiesen wurde.

Das ist nicht der Fall, however- letund const sind hochgezogen (wie var, classund function), aber es ist eine Zeit zwischen der Eingabe und Umfang erklärt wird , wo sie nicht zugegriffen werden kann. Diese Periode ist die zeitliche Totzone (TDZ) .

Die TDZ endet , wenn aLetwird erklärt , anstatt zugeordnet :

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

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

Dieses Beispiel zeigt, dass letgehisst wird:

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

Gutschrift: Temporal Dead Zone (TDZ) entmystifiziert

Der Zugriff xim inneren Bereich verursacht weiterhin a ReferenceError. Wenn letes nicht gehisst würde, würde es sich protokollieren outer value.

Die TDZ ist eine gute Sache, da sie dazu beiträgt, Fehler hervorzuheben. Der Zugriff auf einen Wert, bevor er deklariert wurde, ist selten beabsichtigt.

Die TDZ gilt auch für Standardfunktionsargumente. Argumente werden von links nach rechts ausgewertet, und jedes Argument befindet sich in der TDZ, bis es zugewiesen wird:

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

Die TDZ ist im Transpiler babel.js standardmäßig nicht aktiviert . Aktivieren Sie den "High Compliance" -Modus, um ihn in der REPL zu verwenden . Geben Sie das es6.spec.blockScopingFlag an, um es mit der CLI oder als Bibliothek zu verwenden.

Empfohlene weitere Lektüre: TDZ entmystifiziert und ES6 Let, Const und die „Temporal Dead Zone“ (TDZ) im Detail .

Joews
quelle
3
Ebenfalls interessant: Warum gibt es eine zeitliche Totzone
ein besserer Oliver
@zeroflagL guter Link, danke. Außerdem heißt es: "foo ist nicht nicht deklariert, es ist nicht initialisiert", diese Sprache wäre hilfreich, um die obige Antwort zu klären / zu korrigieren. let fooin einem Block bewirkt, dass er oben in diesem Block angehoben und deklariert wird. Die Zeile let foobewirkt, dass es initialisiert wird. Und foo = xyzbewirkt, dass ihm ein Wert zugewiesen wird.
AJP
2
Ich denke, das ist ein großartiger Beitrag! Ich hatte jedoch den Eindruck, dass 'let' nicht gehisst werden konnte? Ich habe dies in den Mozilla-Dokumenten gefunden: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Ich versuche nicht, ein Curmudgeon zu sein, ich war nur neugierig und bin offen für Klarstellungen.
Dmarges
1
@jeows Die MDN-Seite sagt immer noch, dass sie nicht gehisst werden. Sie sollten versuchen, das zu bearbeiten, wenn Sie wirklich sicher sind, was Sie sagen. Ich denke, ich sollte eine Frage dazu posten.
DoubleOrt
1
@joews IMO, Sie könnten entweder sagen, dass sie gehisst werden, aber aufgrund der TDZ nicht auf sie zugegriffen werden kann, bevor ihre Deklaration erreicht wurde, oder Sie könnten sagen, dass sie nicht gehisst werden, aber die TDZ führt dazu, dass Verweise auf sie einen Fehler auslösen. Praktisch sind beide Aussagen gleichermaßen wahr. Außer, ich denke, Sie verwenden den Begriff "Heben" in einem abstrakten Sinne, wie in "Heben = wann immer der Motor die Existenz dieser Variablen kennt". Ist das Warum ? Und was sagen die technischen Daten dazu?
DoubleOrt
7

Hissen:
let , const, varsind alle get gehisst Prozess.
(Was bedeutet, dass sie nach oben gehen und oben im Bereich deklarieren.)

Initialisierung:

  • varGehen Sie auch durch den Anfangsprozess und erhalten Sie den Anfangswert von undefined.
  • während let, constging nicht den ersten Prozess werfen, so dass ihre Werte immer noch nicht zugänglich sind, obwohl sie bereits erklärt. Was hat sie reingelegt?temporal dead zone

Also in Kürze:

Hubvorgang: var, let, const
Initialisierungsverfahren: var

ofir_aghai
quelle
0

Im Fall von let- und const-Variablen ist die zeitliche Totzone grundsätzlich eine Zone

"bevor Ihre Variable deklariert wird",

Wenn Sie also nicht auf den Wert dieser Variablen zugreifen können, wird ein Fehler ausgegeben.

Ex.

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

Der obige Code gibt einen Fehler aus

Der gleiche Code gibt keinen Fehler aus, wenn wir var für die Variable 'a' verwenden.

Ex.

var sum = a;                            
console.log(sum)     //prints undefined
var a = 5;
Niranjan Harpale
quelle
Das Konsolenprotokoll erzeugt im zweiten Beispiel "NaN" (das Ergebnis des Hinzufügens von undefinedund 5). Die Deklaration von var awird gehisst, der aauf 5 eingestellte Inifialisierungscode nicht.
Traktor53
ja, richtig, a wird ohne Initialisierung gehisst. Ein Wille ist also undefiniert.
Niranjan Harpale
Das erste angeführte Beispiel ist nicht richtig. Bitte korrigieren oder entfernen Sie es.
Spidis Web