@ 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ę.const
takiej decyzjilet
jest wadą projektową. W ramach zakresuconst
powinno się było go podnosić i inicjować dokładnie w czasie, gdy jest dostępny. Naprawdę, powinni miećconst
, jaklet
i innego słowa kluczowego, który tworzy zmienną, która działa jak „tylko do odczytu”let
.Cytując specyfikację ECMAScript 6 (ECMAScript 2015)
let
iconst
sekcję deklaracji ,Tak więc, aby odpowiedzieć na twoje pytanie, tak,
let
iconst
wciągnij, ale nie możesz uzyskać do nich dostępu, dopóki rzeczywista deklaracja nie zostanie oceniona w czasie wykonywania.źródło
ES6
wprowadzaLet
zmienne, które powstająblock level scoping
. DopókiES5
tego nie mieliśmyblock level scoping
, więc zmienne zadeklarowane w bloku zawszehoisted
mają zakres funkcji.Zasadniczo
Scope
odnosi się do tego, gdzie w twoim programie są widoczne twoje zmienne, co określa, gdzie możesz używać deklarowanych zmiennych. WES5
mamyglobal scope,function scope and try/catch scope
, dziękiES6
zakresowi określania poziomu bloków również za pomocą Let.var
słowa kluczowego, znana jest cała funkcja od momentu jej zdefiniowania.Kiedy definiujesz zmienną z
let
instrukcją, jest ona znana tylko w jej bloku.Jeśli uruchomisz kod, zobaczysz, że zmienna
j
jest znana tylko w,loop
a nie przed i po. Jednak nasza zmiennai
jest znanaentire function
od momentu jej zdefiniowania.Jest jeszcze jedna wielka zaleta użycia let, ponieważ tworzy nowe środowisko leksykalne, a także wiąże nową wartość, zamiast utrzymywać stare odniesienie.
Pierwsza
for
pętla zawsze wypisuje ostatnią wartość,let
tworząc nowy zakres i wiążąc świeże wartości drukujące nas1, 2, 3, 4, 5
.Jeśli chodzi o
constants
to, działa w zasadzie taklet
, jedyną różnicą jest to, że ich wartości nie można zmienić. W stałych mutacja jest dozwolona, ale ponowne przypisanie nie jest dozwolone.Jeśli stała odnosi się do
object
, zawsze będzie odnosić się do,object
aleobject
sama w sobie może zostać zmieniona (jeśli jest zmienna). Jeśli chcesz mieć niezmiennyobject
, możesz użyćObject.freeze([])
źródło
Z dokumentów internetowych MDN:
W ECMAScript 2015,
let
iconst
są wydobywanych ale nie zainicjowany. Odwołanie do zmiennej w bloku przed deklaracją zmiennej powoduje,ReferenceError
że zmienna znajduje się w „czasowej martwej strefie” od początku bloku do momentu przetworzenia deklaracji.źródło
w es6, kiedy używamy let lub const, musimy zadeklarować zmienną przed ich użyciem. na przykład. 1 -
na przykład. 2-
źródło