Zmienne to struktura danych, która przypisuje wartości reprezentatywną nazwę. Mogą one zawierać dowolne dane.
Nazwa zmiennej jest nazywana identyfikatorem. Prawidłowy identyfikator musi być zgodny z tymi zasadami:
- Identyfikatory mogą zawierać litery Unicode, znaki dolara ($), podkreślenia (_), cyfry (0–9), a nawet niektóre znaki Unicode.
- Identyfikatory nie mogą zawierać odstępów, bo parser używa odstępów do rozdzielania elementów wejściowych. Jeśli na przykład spróbujesz wywołać zmienną
my Variable
zamiastmyVariable
, parser wykryje 2 identyfikatory:my
iVariable
, a potem zgłosi błąd składni („nieoczekiwany token: identyfikator”). Identyfikatory muszą zaczynać się od litery, podkreślenia (
_
) lub znaku dolara ($
). Nie mogą zaczynać się od cyfr, aby uniknąć pomylenia między liczbami a identyfikatorami:let 1a = true; > Uncaught SyntaxError: Invalid or unexpected token
Jeśli JavaScript dopuszczałby się na początku identyfikatora, dopuszczałoby to stosowanie identyfikatorów składających się tylko z liczb, powodując konflikty między liczbami a liczbami używanymi jako identyfikatory:
let 10 = 20 10 + 5 > ?
„Zarezerwowane słowa, które mają już znaczenie składniowe, nie mogą być używane jako identyfikatory.
Identyfikatory nie mogą zawierać znaków specjalnych (
! . , / \ + - * =
).
Podane niżej reguły nie są rygorystyczne, ale stanowią sprawdzone metody branżowe, które ułatwiają utrzymanie kodu. Jeśli Twój projekt ma inne standardy, zastosuj się do nich, aby zachować spójność.
Na podstawie przykładu wskazanego przez wbudowane metody i właściwości JavaScriptu stosowaną konwencją identyfikatorów składających się z wielu słów jest wielkość wielbłąda (określana również jako „camelCase”). Wielkość liter to metoda, która polega na umieszczaniu pierwszych liter na początku każdego wyrazu z wyjątkiem pierwszej, aby poprawić czytelność tekstu bez spacji.
let camelCasedIdentifier = true;
W niektórych projektach stosowane są inne konwencje nazewnictwa w zależności od kontekstu i charakteru danych. Na przykład pierwsza litera nazwy klasy jest zwykle pisana wielką literą, dlatego w nazwach klas wielowyrazowych często stosuje się pisownię wielkimi literami wielbłąda, nazywaną też „wielkią literą wielbłąda” lub „Pascalem”.
class MyClass {
}
Identyfikatory powinny zwięźle opisać charakter zawartych w nich danych (np. currentMonthDays
to lepsza nazwa niż theNumberOfDaysInTheCurrentMonth
) i szybko je odczytać (originalValue
jest lepszy niż val
). Identyfikatory myVariable
używane w tym module działają w kontekście wyodrębnionych przykładów, ale byłyby bardzo nieprzydatne w kodzie produkcyjnym, ponieważ nie zawierają informacji o zawartościach identyfikatorów.
Identyfikatory nie powinny być zbyt szczegółowe w odniesieniu do zawartych w nich danych, ponieważ ich wartości mogą się zmieniać w zależności od tego, jak skrypty korzystają z tych danych, lub od decyzji podejmowanych przez przyszłych opiekunów. Na przykład zmienną, oryginalnie podającą identyfikator miles
, może trzeba będzie zmienić w kilometrach później w projekcie, co będzie wymagało zmiany odwołań do tej zmiennej, aby uniknąć nieporozumień w przyszłości. Aby temu zapobiec, użyj distance
jako identyfikatora.
JavaScript nie nadaje żadnych specjalnych uprawnień ani znaczenia identyfikatorom rozpoczynającym się od znaku podkreślenia (_
), ale zwykle używa się ich do pokazania, że zmienna, metoda lub właściwość są „prywatne”, co oznacza, że jest przeznaczona do użytku wyłącznie w kontekście obiektu, który je zawiera, i nie należy do niej uzyskiwać dostępu ani modyfikować poza tym kontekstem. Jest to konwencja przeniesiona z innych języków programowania, która poprzedzała dodanie prywatnych właściwości JavaScriptu.
Deklaracja zmiennej
Jest wiele sposobów na rozpoznanie identyfikatora przez JavaScript. Jest to proces nazywany „deklarowaniem” zmiennej. Zmienna jest deklarowana za pomocą słów kluczowych let
, const
lub var
.
let myVariable;
Użyj funkcji let
lub var
, aby zadeklarować zmienną, którą można w każdej chwili zmienić. Te słowa kluczowe informują tłumacze JavaScriptu, że ciąg znaków jest identyfikatorem, który może zawierać wartość.
Pracując w nowoczesnej bazie kodu, używaj let
zamiast var
. var
nadal działa w nowoczesnych przeglądarkach, ale ma pewne nieintuicyjne działania zdefiniowane w najstarszych wersjach JavaScriptu, którego nie można później zmienić, by zachować zgodność wsteczną. W ES6 dodaliśmy let
, aby rozwiązać problemy z projektem var
.
Zadeklarowana zmienna jest inicjowana przez przypisanie do niej wartości. Aby przypisać lub zmienić wartość zmiennej, użyj pojedynczego znaku równości (=
). Możesz to zrobić w ramach tego samego oświadczenia:
let myVariable = 5;
myVariable + myVariable
> 10
Możesz też zadeklarować zmienną z parametrem let
(lub var
) bez jej inicjowania. Jeśli to zrobisz, początkowa wartość zmiennej będzie wynosić undefined
, dopóki nie zostanie jej przypisana przez kod.
let myVariable;
myVariable;
> undefined
myVariable = 5;
myVariable + myVariable
> 10
Zmienna z wartością undefined
różni się od niezdefiniowanej zmiennej, której identyfikator nie został jeszcze zadeklarowany. Odwołanie do niezadeklarowanej zmiennej
powoduje błąd.
myVariable
> Uncaught ReferenceError: myVariable is not defined
let myVariable;
myVariable
> undefined
Powiązanie identyfikatora z wartością jest zwykle nazywane „powiązaniem”.
Składnia, która występuje po słowach kluczowych let
, var
lub const
, jest nazywana „listą powiązań” i pozwala na utworzenie wielu deklaracji zmiennych rozdzielonych przecinkami (kończących się oczekiwanym średnikiem). Dzięki temu poniższe fragmenty kodu
działają tak samo:
let firstVariable,
secondVariable,
thirdVariable;
let firstVariable;
let secondVariable;
let thirdVariable;
Ponowne przypisanie wartości zmiennej nie spowoduje użycia właściwości let
(ani var
), ponieważ JavaScript wie już, że zmienna istnieje:
let myVariable = true;
myVariable
> true
myVariable = false;
myVariable
> false
Możesz przypisywać zmiennym nowe wartości na podstawie ich istniejących wartości:
let myVariable = 10;
myVariable
> 10
myVariable = myVariable * myVariable;
myVariable
> 100
Jeśli spróbujesz ponownie zadeklarować zmienną za pomocą funkcji let
w środowisku produkcyjnym, pojawi się błąd składni:
let myVariable = true;
let myVariable = false;
> Uncaught SyntaxError: redeclaration of let myVariable
Narzędzia dla programistów w przeglądarkach mniej rygorystycznie podchodzą do ponownej deklaracji let
(i class
), więc ten sam błąd może się nie pojawić w konsoli programisty.
Aby zachować zgodność ze starszą wersją przeglądarek, var
umożliwia niepotrzebne ponowne deklaracja bez błędów w żadnym kontekście:
var myVariable = true;
var myVariable = false;
myVariable\
> false
const
Za pomocą słowa kluczowego const
możesz zadeklarować stałą, czyli typ zmiennej, którą trzeba natychmiast zainicjować, a potem nie można jej zmienić. Identyfikatory stałych są zgodne z tymi samymi regułami co zmienne zadeklarowane za pomocą funkcji let
(i var
):
const myConstant = true;
myConstant
> true
Nie możesz zadeklarować stałej bez natychmiastowego przypisania jej wartości, ponieważ stałych wartości nie można zmieniać po ich utworzeniu, więc każda niezainicjowana stała będzie obowiązywać przez zawsze undefined
. Jeśli spróbujesz zadeklarować stałą bez jej zainicjowania, pojawi się błąd składni:
const myConstant;
Uncaught SyntaxError: missing = in const declaration
Próba zmiany wartości zmiennej zadeklarowanej za pomocą funkcji const
w taki sposób, w jaki można zmienić wartość zmiennej zadeklarowanej za pomocą funkcji let
(lub var
), powoduje błąd typu:
const myConstant = true;
myConstant = false;
> Uncaught TypeError: invalid assignment to const 'myConstant'
Jeśli jednak z obiektem powiązana jest stała, można zmieniać właściwości tego obiektu.
const constantObject = { "firstvalue" : true };
constantObject
> Object { firstvalue: true }
constantObject.secondvalue = false;
constantObject
> Object { firstvalue: true, secondvalue: false }
Stała, która zawiera obiekt, jest trwałym odwołaniem do zmiennej wartości danych. Chociaż nie można zmienić samej stałej, można zmodyfikować, dodać lub usunąć właściwości obiektu, do którego odwołuje się obiekt:
const constantObject = { "firstvalue" : true };
constantObject = false
> Uncaught TypeError: invalid assignment to const 'constantObject'
Jeśli nie spodziewasz się ponownego przypisania zmiennej, najlepiej ustawić ją jako stałą. Użycie właściwości const
informuje zespół programistów lub przyszłych opiekunów projektu, aby nie zmieniali tej wartości. Pozwoli to uniknąć naruszenia założeń dotyczących sposobu wykorzystania kodu (na przykład że zmienna zostanie ostatecznie oceniana pod kątem oczekiwanego typu danych).
Zakres zmiennej
Zakres zmiennej to część skryptu, w której ta zmienna jest dostępna.
Poza zakresem zmiennej nie zostanie ona zdefiniowana – nie jako identyfikator zawierająca wartość undefined
, ale jak gdyby nie została zadeklarowana.
W zależności od słowa kluczowego, którego używasz do zadeklarowania zmiennej, i kontekstu, w którym ją zdefiniujesz, możesz określić zakres zmiennych, by blokować instrukcje (zakres blokowania), poszczególne funkcje (zakres funkcji) lub całą aplikację JavaScript (zakres globalny).
Zablokuj zakres
Każda zmienna zadeklarowana za pomocą let
lub const
jest ograniczona do najbliższej zawierającej instrukcję blokowania, co oznacza, że dostęp do zmiennej można uzyskać tylko w obrębie tego bloku. Próba uzyskania dostępu do zmiennej o zakresie na poziomie bloku poza jej blokiem, który zawiera, powoduje ten sam błąd co w przypadku próby uzyskania dostępu do zmiennej, która nie istnieje:
{
let scopedVariable = true;
console.log( scopedVariable );
}
> true
scopedVariable
> ReferenceError: scopedVariable is not defined
W przypadku JavaScriptu poza bloku, który go zawiera, nie występuje zmienna o zakresie na poziomie bloku. Na przykład możesz zadeklarować stałą w bloku, a następnie inną stałą poza tym blokiem, która korzysta z tego samego identyfikatora:
{
const myConstant = false;
}
const myConstant = true;
scopedConstant;
> true
Chociaż zadeklarowana zmienna nie może wykraczać poza swój blok nadrzędny, jest dostępna dla wszystkich bloków podrzędnych:
{
let scopedVariable = true;
{
console.log( scopedVariable );
}
}
> true
Wartość zadeklarowanej zmiennej można zmienić z poziomu bloku podrzędnego:
{
let scopedVariable = false;
{
scopedVariable = true;
}
console.log( scopedVariable );
}
> true
Nową zmienną można zainicjować bez błędów za pomocą let
lub const
wewnątrz bloku podrzędnego, nawet jeśli używa ona tego samego identyfikatora co zmienna w bloku nadrzędnym:
{
let scopedVariable = false;
{
let scopedVariable = true;
}
console.log( scopedVariable );
}
> false
Zakres funkcji
Zmienne zadeklarowane za pomocą funkcji var
są ograniczone do najbliższej funkcji zawierającej (lub statycznego bloku inicjowania w klasie).
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
Dzieje się tak nadal po wywołaniu funkcji. Mimo że zmienna jest inicjowana w trakcie wykonywania funkcji, nadal jest niedostępna poza zakresem funkcji:
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
myFunction();
> true
scopedVariable;
> ReferenceError: scopedVariable is not defined
Zakres globalny
Zmienna globalna jest dostępna w całej aplikacji JavaScript, niezależnie od bloków i funkcji, dla każdego skryptu na stronie.
Choć może się to wydawać pożądaną wartością domyślną, zmienne, do których dowolna część aplikacji może uzyskiwać dostęp i które mogą być modyfikowane, mogą zwiększyć nakład pracy, a nawet powodować kolizje ze zmiennymi w innym miejscu aplikacji o tym samym identyfikatorze. Dotyczy to całego kodu JavaScriptu związanego z renderowaniem strony, w tym bibliotek zewnętrznych i statystyk użytkowników. Dlatego w miarę możliwości należy unikać zanieczyszczenia zakresu globalnego.
Każda zmienna zadeklarowana za pomocą funkcji var
poza funkcją nadrzędną lub za pomocą funkcji let
bądź const
poza blokiem nadrzędnym jest globalna:
var functionGlobal = true; // Global
let blockGlobal = true; // Global
{
console.log( blockGlobal );
console.log( functionGlobal );
}
> true
> true
(function() {
console.log( blockGlobal );
console.log( functionGlobal );
}());
> true
> true
Przypisanie wartości do zmiennej bez jej jawnego zadeklarowania (czyli nigdy do jej utworzenia za pomocą elementów var
, let
ani const
) podnosi zmienną do zakresu globalnego, nawet jeśli została zainicjowana w ramach funkcji lub bloku. Zmienna utworzona z użyciem tego wzorca jest czasami nazywana „domniemanym globalnym”.
function myFunction() {
globalVariable = "global";
return globalVariable
}
myFunction()\
> "global"
globalVariable\
> "global"
Z możliwością podnoszenia
Zmienne i deklaracje funkcji są przenoszone na początek zakresu, co oznacza, że interpreter JavaScript przetwarza wszystkie zmienne zadeklarowane w dowolnym punkcie skryptu i skutecznie przenosi je do pierwszego wiersza zakresu obejmującego przed wykonaniem skryptu. Oznacza to, że do zmiennej zadeklarowanej za pomocą var
można się odwołać przed jej zadeklarowaniem bez wystąpienia błędu:
hoistedVariable
> undefined
var hoistedVariable;
Ponieważ hostowana jest tylko deklaracja zmiennej, a nie inicjowanie, zmienne, które nie zostały jawnie zadeklarowane za pomocą var
, let
lub const
, nie są przesyłane:
unhoistedVariable;
> Uncaught ReferenceError: unhoistedVariable is not defined
unhoistedVariable = true;
Jak już wspomnieliśmy, do zadeklarowanej, ale niezainicjowanej zmiennej, przypisywana jest wartość undefined
. Odnosi się to też do deklaracji zmiennych przeniesionych, ale tylko do tych zadeklarowanych za pomocą funkcji var
.
hoistedVariable
> undefined
var hoistedVariable = 2 + 2;
hoistedVariable\
> 4
To nieintuicyjne działanie jest w dużej mierze podstawą decyzji projektowych podejmowanych w najstarszych wersjach JavaScriptu i nie można zmienić bez ryzyka uszkodzenia istniejących witryn.
Metody let
i const
rozwiązują ten problem, ponieważ generują błąd w przypadku uzyskania dostępu do zmiennej przed jej utworzeniem:
{
hoistedVariable;
let hoistedVariable;
}
> Uncaught ReferenceError: can't access lexical declaration 'hoistedVariable' before initialization
Różni się on od błędu „hoistedużywanie niezdefiniowanej zmiennej”, który możesz spodziewać się przy próbie uzyskania dostępu do niezadeklarowanej zmiennej. JavaScript pobrał zmienną, więc wie, że zostanie ona utworzona w określonym zakresie. Jednak zamiast udostępniać tę zmienną przed jej deklaracjami z wartością undefined
, interpreter zgłasza błąd.
Zmienne zadeklarowane z funkcją let
lub const
(albo class
) stwierdzają, że istnieją w „tymczasowej martwej strefie” („TDZ”) od początku ich bloku do punktu w kodzie, w którym zmienna jest zadeklarowana.
Tymczasowa strefa martwych danych sprawia, że zachowanie autora let
jest bardziej intuicyjne niż działanie var
. Ważny jest także projekt urządzenia const
. Nie można zmieniać stałych, dlatego nie można zainicjować stałej wartości podniesionej na początek zakresu i przypisanej do niej niejawnej wartości undefined
z wartością znaczącą.
Sprawdź swoją wiedzę
Od jakich znaków możesz zacząć identyfikator?
Jaka jest preferowana metoda deklarowania zmiennej, której wartość można w dowolnym momencie zmienić?