@ theourourtheye ma rację mówiąc, że do tych zmiennych nie można uzyskać dostępu przed ich zadeklarowaniem. Jest to jednak nieco bardziej skomplikowane.
Czy zmienne są zadeklarowane z podniesieniem letczy constnie? Co się tu naprawdę dzieje?
Wszystkie deklaracje ( var, let, const, function, function*, class) są "podniósł" w JavaScript. Oznacza to, że jeśli nazwa zostanie zadeklarowana w zakresie, w tym zakresie identyfikator zawsze będzie odnosił się do tej konkretnej zmiennej:
x = "global";
// function scope:
(function() {
x; // not "global"
var/let/… x;
}());
// block scope (not for `var`s):
{
x; // not "global"
let/const/… x;
}
Dotyczy to zarówno zakresów funkcji, jak i zakresów bloków 1 .
Różnica między var/ function/ function*deklaracjami i let/ const/ classdeklaracjami polega na inicjalizacji .
Te pierwsze są inicjowane za pomocą undefinedfunkcji (generator) zaraz po utworzeniu powiązania u góry zakresu. Jednak zmienne zadeklarowane leksykalnie pozostają niezainicjowane . Oznacza to, że ReferenceErrorzgłaszany jest wyjątek podczas próby uzyskania do niego dostępu. Zostanie zainicjowany tylko podczas oceny instrukcji let/ const/ class, wszystko przed (powyżej), które nazywa się tymczasową martwą strefą .
x = y = "global";
(function() {
x; // undefined
y; // Reference error: y is not defined
var x = "local";
let y = "local";
}());
Zauważ, że let y;instrukcja inicjuje zmienną za pomocą undefinedpodobnego let y = undefined;.
Czasowa strefa martwa nie jest składniowym lokalizacja, ale raczej czas pomiędzy zmiennej (zakres) utworzenia i inicjalizacji. Odwoływanie się do zmiennej w kodzie powyżej deklaracji nie jest błędem, dopóki ten kod nie jest wykonywany (np. Treść funkcji lub po prostu martwy kod), i zgłosi wyjątek, jeśli uzyskasz dostęp do zmiennej przed inicjalizacją, nawet jeśli dostęp kod znajduje się poniżej deklaracji (np. w deklaracji funkcji podniesionej, która jest wywoływana zbyt wcześnie).
Czy jest jakaś różnica między leti constw tej kwestii?
Nie, działają one tak samo, jak w odniesieniu do podnoszenia. Jedyna różnica między nimi polega na tym, że constmrówka musi być i może być przypisana tylko w części inicjalizującej deklaracji ( const one = 1;zarówno const one;przypisania , jak i późniejsze, takie jak one = 2są nieprawidłowe).
1: varDeklaracje nadal działają oczywiście tylko na poziomie funkcji
let foo = () => bar; let bar = 'bar'; foo();ilustruje, że wszystkie deklaracje są podnoszone jeszcze lepiej, ponieważ nie jest to oczywiste ze względu na czasową martwą strefę.