Co to jest czasowa martwa strefa?


150

Słyszałem, że uzyskiwanie dostępu leti constwartości przed ich zainicjowaniem może spowodować ReferenceErrorcoś, co nazywa się czasową martwą strefą .

Co to jest czasowa martwa strefa, jaki ma związek z zasięgiem i podnoszeniem oraz w jakich sytuacjach występuje?


6
możliwy duplikat Czy zmienne zadeklarowane z let lub const nie są podnoszone w ES6? - chociaż pytanie nie koncentruje się na TDZ, odpowiedzi są w zasadzie takie same
Bergi

Odpowiedzi:


201

leti constmają dwie duże różnice w stosunku do var:

  1. Mają zasięg blokowy .
  2. Uzyskanie dostępu do a varprzed jego zadeklarowaniem daje wynik undefined; dostęp do letlub constprzed deklaracją rzuca ReferenceError:

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

Z tych przykładów wynika, że letdeklaracje (i const, które działają w ten sam sposób) nie mogą być podnoszone , ponieważ aLetnie wydaje się istnieć przed przypisaniem jej wartości.

To nie jest przypadek, however- leti const wydobywanych (jak var, classi function), ale nie jest to okres pomiędzy wejściem do zakresu i zadeklarowane w przypadku gdy nie można uzyskać. Ten okres jest czasową martwą strefą (TDZ) .

TDZ kończy się, gdy aLetzostanie zadeklarowany , a nie przypisany :

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

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

Ten przykład pokazuje, że letjest podnoszony:

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

Kredyt: Temporal Dead Zone (TDZ) bez tajemnic

Dostęp xdo zakresu wewnętrznego nadal powoduje ReferenceError. Gdyby letnie był podnoszony, rejestrowałby się outer value.

TDZ to dobra rzecz, ponieważ pomaga wyróżnić błędy - dostęp do wartości przed jej zadeklarowaniem rzadko jest zamierzony.

TDZ ma również zastosowanie do domyślnych argumentów funkcji. Argumenty są oceniane od lewej do prawej, a każdy argument znajduje się w TDZ, dopóki nie zostanie przypisany:

// 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 nie jest domyślnie włączony w transpilerze babel.js. Włącz tryb „wysokiej zgodności”, aby używać go w REPL . Podaj es6.spec.blockScopingflagę, aby użyć jej z interfejsem wiersza polecenia lub jako biblioteką.

Zalecane dalsze lektury: TDZ zdemistyfikowany i ES6 Let, Const i „Temporal Dead Zone” (TDZ) in Depth .



@zeroflagL dobry link, dzięki. Mówi się również: „foo nie jest niezadeklarowane, jest niezainicjalizowane”, ten język byłby pomocny w wyjaśnieniu / poprawieniu powyższej odpowiedzi. let foow bloku powoduje jego podniesienie i zadeklarowanie na górze tego bloku. Linia of let foopowoduje jej zainicjowanie. I foo = xyzpowoduje przypisanie mu wartości.
AJP

2
Myślę, że to świetny post! Miałem jednak wrażenie, że „niech” nie podlega podnoszeniu? Znalazłem to w dokumentacji Mozilli: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Nie próbuję być zrzędą, byłem po prostu zaciekawiony i otwarty na wyjaśnienia.
dmarges

1
@jeows Strona MDN nadal informuje, że nie zostały one podniesione. Powinieneś spróbować to zmienić, jeśli jesteś naprawdę pewien tego, co mówisz. Myślę, że powinienem zadać pytanie na ten temat.
doubleOrt

1
@joews IMO, możesz albo powiedzieć, że są podniesione, ale nie można uzyskać do nich dostępu przed osiągnięciem ich deklaracji z powodu TDZ, lub możesz powiedzieć, że nie są podnoszone, ale TDZ spowoduje, że wszelkie odniesienia do nich spowodują błąd. Praktycznie oba stwierdzenia są jednakowo prawdziwe. Z wyjątkiem, myślę, że używasz terminu „podnoszenie” w sensie abstrakcyjnym, na przykład „podnoszenie = zawsze, gdy silnik jest świadomy istnienia tej zmiennej”. Czy to dlatego ? Poza tym, co na ten temat mówią specyfikacje?
doubleOrt

7

Wyciągowych:
let , const, varto wszyscy się podnieśli proces.
(co oznacza, że ​​idą wyżej i deklarują się na szczycie zakresu.)

Inicjalizacja:

  • varprzejść również przez początkowy proces i uzyskać wartość początkową undefined.
  • podczas gdy let, constnie rzucił początkowego procesu, więc ich wartości są nadal niedostępne, chociaż już zadeklarowali. co je włożyłotemporal dead zone

Więc w skrócie:

Sposób podnoszenia: var, let, const
proces inicjalizacji: var


0

W przypadku zmiennych let i const, Zasadniczo, czasowa martwa strefa jest strefą

"przed zadeklarowaniem zmiennej",

tzn. jeśli nie możesz uzyskać dostępu do wartości tych zmiennych, spowoduje to błąd.

dawny.

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

powyższy kod daje błąd

ten sam kod nie spowoduje błędu, gdy użyjemy var dla zmiennej „a”,

dawny.

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

dziennik konsoli generuje „NaN” w drugim przykładzie (wynik dodawania undefinedi 5). Declaratation od var ajest podciągnięta The settng kod inifialisation ado 5 nie jest.
traktor53

tak, tak, a jest podnoszony bez żadnej inicjalizacji. Więc będzie niezdefiniowany.
niranjan harpale

Pierwszy zacytowany przykład jest nieprawidłowy, popraw go lub usuń.
Spidi's Web
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.