@ 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 let
czy const
nie? 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
/ class
deklaracjami polega na inicjalizacji .
Te pierwsze są inicjowane za pomocą undefined
funkcji (generator) zaraz po utworzeniu powiązania u góry zakresu. Jednak zmienne zadeklarowane leksykalnie pozostają niezainicjowane . Oznacza to, że ReferenceError
zgł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ą undefined
podobnego 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 let
i const
w tej kwestii?
Nie, działają one tak samo, jak w odniesieniu do podnoszenia. Jedyna różnica między nimi polega na tym, że const
mró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 = 2
są nieprawidłowe).
1: var
Deklaracje 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ę.