2015-10-18 16 views
69

Słyszałem, że uzyskanie dostępu do wartości let i const przed ich zadeklarowaniem może spowodować ReferenceError z powodu czegoś, co nazywa się strefą nieczynną czasową .Co to jest martwa strefa czasowa?

Co to jest martwa strefa czasowa, w jaki sposób odnosi się do zasięgu i podnoszenia, oraz w jakich sytuacjach jest napotykana?

+4

możliwy duplikat [Czy zmienne zadeklarowane z let or const nie zostały wyciągnięte w ES6?] (Http://stackoverflow.com/q/31219420/1048572) - chociaż pytanie nie koncentruje się na TDZ, odpowiedzi są zasadniczo ten sam – Bergi

Odpowiedz

101

let i const mieć dwa szerokie różnice z var:

  1. Oni są block scoped.
  2. Uzyskanie dostępu do var przed zadeklarowaniem ma wynik undefined; dostępu do let lub const zanim zostanie zadeklarowana rzuca ReferenceError:

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

Jak wynika z tych przykładów, które let deklaracje (i const, który działa w ten sam sposób) może nie być hoisted, ponieważ aLet wydaje się nie istnieć przed przypisaniem jej wartości.

Nie jest to przypadek, however- let i const podnoszonego (jak var, class i function), lecz jest to okres pomiędzy wejściem zakresu i jest podawana, o ile nie są dostępne. Ten okres jest martwą strefą czasową (TDZ).

TDZ kończy się aLet jest uznane, zamiast przypisany:

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

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

Przykład ten pokazuje, że let podnoszony jest:

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

Credit: Temporal Dead Zone (TDZ) demystified

Dostęp x w zakresie wewnętrznego nadal powoduje ReferenceError. Jeśli let nie zostały podniesione, logowałoby się outer value.

TDZ to dobra rzecz, ponieważ pomaga uwypuklić błędy - dostęp do wartości, zanim zostanie zadeklarowany, rzadko jest celowy.

TDZ dotyczy także domyślnych argumentów funkcji.Argumenty są oceniane od lewej do prawej, a każdy argument jest 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łączona w babel.js transpiler. Włącz tryb "wysokiej zgodności", aby użyć go w urządzeniu REPL. Podaj flagę es6.spec.blockScoping, aby użyć jej z interfejsem CLI lub biblioteką.

Zalecane dalsze czytanie: TDZ demystified i ES6 Let, Const and the “Temporal Dead Zone” (TDZ) in Depth.

+0

'b nie jest zdefiniowany' (jako komentarz pierwszego fragmentu kodu), ale myślę, że zmieniłeś nazwy zmiennych w międzyczasie (i napisz o tym później ponownie) – oliverpool

+3

Również interesujące: [Dlaczego istnieje czasowa martwa strefa] (http://www.2ality.com/2015/10/why-tdz.html) – zeroflagL

+0

@zeroflagL dobry link, dzięki. Mówi także: "foo nie jest niezadeklarowane, nie jest zainicjowane", to język będzie pomocny w wyjaśnieniu/poprawieniu w powyższej odpowiedzi. 'let foo' w bloku powoduje, że jest on podnoszony i deklarowany na górze tego bloku. Linia 'let foo' powoduje jej inicjalizację. Natomiast 'foo = xyz' powoduje przypisanie mu wartości. – AJP