Tudom, hogy a Temporal Dead Zone sci-fi kifejezésnek hangzik. De hasznos megérteni, hogy mit jelentenek azok a kifejezések és fogalmak, amelyekkel mindennap dolgozol (vagy meg akarsz ismerkedni).
Csatolja be, mert ez bonyolulttá válik.
Tudja, hogy a JavaScript-ben { }
hozzáadhatunk egy hatókörszintet, ahol csak akarjuk?
Tehát mindig a következőket tehettük:
{ { { { { { var madness = true } } } } } }
Azért vettem fel ezt a részletet, hogy megbizonyosodjak arról, hogy a következő példáknak van-e értelme (mivel nem akartam feltételezni, hogy mindenki ismeri).
Az ES6 előtt nem volt más lehetőség a változók deklarálására, mint a var
. De az ES6 hozott minket let
és const
.
let
és a const
deklarációk egyaránt blokk hatókörűek, ami azt jelenti, hogy csak a {
}
körülöttük érhetők el. var
másrészt nincs megadva ez a korlátozás.
Íme egy példa:
let babyAge = 1; let isBirthday = true; if (isBirthday) { let babyAge = 2; } console.log(babyAge); // Hmmmm. This prints 1
A fentiek azért történtek, mert a 2-re történő újbóli deklarálás babyAge
csak a if
blokkon belül érhető el. Ezen túl az elsőt babyAge
használják. Látja, hogy két különböző változóról van szó?
Ezzel szemben a var
nyilatkozatnak nincs blokk hatálya:
var babyAge = 1; var isBirthday = true; if (isBirthday) { var babyAge = 2; } console.log(babyAge); // Ah! This prints 2
A végső szembeötlő különbség let
/ const
és var
az, hogy ha nyilvános var
mielőtt az nyilvánították, akkor definiálatlan. De ha ugyanezt teszi a let
és miatt const
, akkor dobnak egy ReferenceError
.
console.log(varNumber); // undefined console.log(letNumber); // Doesn't log, as it throws a ReferenceError letNumber is not defined var varNumber = 1; let letNumber = 1;
A hibát mind a Temporal Dead Zone miatt dobják.
Az Temporal Dead Zone elmagyarázta
Ez az, ami a TDZ: az az állapot leírására, ahol a változók nem érhetők el. Hatókörbe tartoznak, de nincsenek bejelentve.
Az let
ésconst
változók a TDZ-ben a körük kezdetétől a deklarálásig léteznek.
Azt is mondhatnánk, hogy a változók a TDZ-ben attól a helytől léteznek, ahová lekötik őket (amikor a változó a belsejében lévő hatókörhöz kötődik), amíg ki nem deklarálják (amikor egy név fenntartva a memóriában ennek a változónak).
{ // This is the temporal dead zone for the age variable! // This is the temporal dead zone for the age variable! // This is the temporal dead zone for the age variable! // This is the temporal dead zone for the age variable! let age = 25; // Whew, we got there! No more TDZ console.log(age); }
Láthatja fentebb, hogy ha korábban elérem a kor változót, mint a deklarációja, akkor a ReferenceError
. A TDZ miatt.
De var
nem fogja megtenni. var
csak alapértelmezés szerint inicializálva van undefined
a másik deklarációval ellentétben.
Mi a különbség a deklarálás és az inicializálás között?
Itt van egy példa egy változó deklarálására és egy változó inicializálására.
function scopeExample() { let age; // 1 age = 20; // 2 let hands = 2; // 3 }
Egy változó deklarálása azt jelenti, hogy a nevet a memóriában fenntartjuk az aktuális hatókörön belül. Ez a megjegyzésekben 1-et jelöl.
Egy változó inicializálása a változó értékének beállítása. Ezt a megjegyzésekben 2-vel jelölik.
Vagy mindig megteheti mindkettőt egy vonalon. Ez a megjegyzésekben 3-al van jelölve.
Csak, hogy ismét megismételjem magam: a let
ésconst
változók a TDZ-ben a körük kezdetétől a deklarálásig léteznek.
Tehát a fenti kódrészletből hol a TDZ age
? Továbbá hands
van TDZ- je ? Ha igen, hol van a TDZ kezdete és vége a kezek számára?
A kezek TDZ-je akkor ér véget, amikor deklarálva van, ugyanaz a vonal 2-re áll.
Az életkorra vonatkozó TZ véget ér, amikor deklarálják, és a név a memóriában van fenntartva (a 2. lépésben, ahol megjegyzést fűztem).
Miért jön létre a TDZ, amikor van?
Térjünk vissza az első példánkra:
{ // This is the temporal dead zone for the age variable! // This is the temporal dead zone for the age variable! // This is the temporal dead zone for the age variable! // This is the temporal dead zone for the age variable! let age = 25; // Whew, we got there! No more TDZ console.log(age); }
Ha hozzáadunk egy console.log
belső helyet a TDZ-hez, akkor ezt a hibát látja:

Miért van a TDZ a hatókör teteje és a változó deklaráció között? Mi ennek a konkrét oka?
Az emelés miatt van.
A kódot elemző és végrehajtó JS motornak két lépése van:
- A kód elemzése absztrakt szintaxisfába / futtatható bájtkódra, és
- Futtatási idő végrehajtása.
Az 1. lépésben történik az emelés, és ezt a JS motor végzi. Lényegében az összes változó deklarációját a hatókörének tetejére helyezi. Tehát egy példa lenne:
console.log(hoistedVariable); // undefined var hoistedVariable = 1;
Az egyértelműség érdekében ezek a változók fizikailag nem mozognak a kódban. De az eredmény funkcionálisan megegyezik az alábbiakkal:
var hoistedVariable; console.log(hoistedVariable); // undefined counter = 1;
Az egyetlen különbség const
és let
az, hogy amikor fel vannak emelve, akkor az értékeik nem lesznek alapértelmezettek undefined
.
Csak bebizonyításra let
és const
emelésre, itt van egy példa:
{ // Both the below variables will be hoisted to the top of their scope! console.log(typeof nonsenseThatDoesntExist); // Prints undefined console.log(typeof name); // Throws an error, cannot access 'name' before initialization let name = "Kealan"; }
A fenti részlet egy bizonyíték, let
amely egyértelműen fel van emelve, ahol deklarálták, mivel a motor figyelmeztet bennünket a tényre. Tudja, hogy name
létezik (deklarálva van), de az inicializálás előtt nem férhetünk hozzá.
Ha ez segít emlékezni, gondoljon így.
When variables get hoisted, var
gets undefined
initialized to its value by default in the process of hoisting. let
and const
also get hoisted, but don't get set to undefined
when they get hoisted.
And that's the sole reason we have the TDZ. Which is why it happens with let
and const
but not var
.
More examples of the TDZ
The TDZ can also be created for default function parameters. So something like this:
function createTDZ(a=b, b) { } createTDZ(undefined, 1);
throws a ReferenceError
, because the evaluation of variable a
tries to access variable b
before it has been parsed by the JS engine. The function arguments are all inside the TDZ until they are parsed.
Even something as simple as let tdzTest = tdzTest;
would throw an error due to the TDZ. But var
here would just create tdzTest
and set it to undefined
.
There's one more final and fairly advanced example from Erik Arvindson (who's involved in evolving and maintaining the ECMAScript spec):
let a = f(); // 1 const b = 2; function f() { return b; } // 2, b is in the TDZ
You can follow the commented numbers.
In the first line we call the f
function, and then try to access the b
variable (which throws a ReferenceError
because b
is in the TDZ).
Why do we have the TDZ?
Dr Alex Rauschmayer has an excellent post on why the TDZ exists, and the main reason is this:
It helps us catch errors.
To try and access a variable before it is declared is the wrong way round, and shouldn't be possible.
It also gives more expected and rational semantics for const
(because const
is hoisted, what happens if a programmer tries to use it before it is declared at runtime? What variable should it hold at the point when it gets hoisted?), and was the best approach decided by the ECMAScript spec team.
How to avoid the issues the TDZ causes
Relatively simply, always make sure you define your let
s and const
s at the top of your scope.