Zmienne to struktura danych, która przypisuje nazwę substytutową do wartości. Mogą one zawierać dowolne dane.
Nazwa zmiennej to identyfikator. Prawidłowy identyfikator musi być zgodny z tymi regułami:
- Identyfikatory mogą zawierać litery Unicode, znaki dolara ($), podkreślenia (_), cyfry (0–9) i nawet niektóre znaki Unicode.
- Identyfikatory nie mogą zawierać spacji, ponieważ parsujący je program używa spacji do rozdzielania elementów danych wejściowych. Jeśli na przykład spróbujesz wywołać zmienną
my Variable
zamiastmyVariable
, parsujący zobaczy 2 identyfikatory:my
iVariable
, i wygeneruje błąd składni („nieoczekiwany element: identyfikator”). Identyfikatory muszą zaczynać się od litery, podkreślenia (
_
) lub znaku dolara ($
). Nie mogą zaczynać się od cyfr, aby uniknąć pomyłek między cyframi a identyfikatorami:let 1a = true; > Uncaught SyntaxError: Invalid or unexpected token
Jeśli JavaScript zezwalałby na liczby na początku identyfikatora, pozwoliłoby to na identyfikatory składające się tylko z liczb, co spowoduje konflikty między liczbami używanymi jako liczby a liczbami używanymi jako identyfikatory:
let 10 = 20 10 + 5 > ?
„Zarezerwowane słowa”, które mają już znaczenie syntaktyczne, nie mogą być używane jako identyfikatory.
Identyfikatory nie mogą zawierać znaków specjalnych (
! . , / \ + - * =
).
Poniższe wskazówki to nie ścisłe reguły tworzenia identyfikatorów, ale sprawdzone metody branżowe, które ułatwiają utrzymanie kodu. Jeśli Twój projekt ma inne standardy, stosuj je, aby zachować spójność.
Zgodnie z przykładem korzystania z wbudowanych metod i właściwości JavaScriptu wielkie litery w słowie (także stylizowane jako „camelCase”) to bardzo powszechna konwencja w przypadku identyfikatorów złożonych z kilku słów. Camel case to praktyka polegająca na pisaniu wielkimi literami pierwszej litery każdego słowa oprócz pierwszej, aby ułatwić czytelność bez użycia spacji.
let camelCasedIdentifier = true;
Niektóre projekty stosują inne konwencje nazewnictwa w zależności od kontekstu i charakteru danych. Na przykład pierwsza litera klasy jest zwykle pisana wielką literą, więc nazwy klas składające się z wielu słów często używają wariantu formatu „wielkie litery z kropką” lub Pascal.
class MyClass {
}
Identyfikatory powinny w zwięzły sposób opisywać charakter danych, które zawierają (na przykład currentMonthDays
jest lepszą nazwą niż theNumberOfDaysInTheCurrentMonth
) oraz być czytelne na pierwszy rzut oka (originalValue
jest lepszy niż val
). Identyfikatory myVariable
użyte w tym module działają w kontekście pojedynczych przykładów, ale nie są przydatne w produkcyjnym kodzie, ponieważ nie zawierają informacji o zawartych w nich danych.
Identyfikatory nie powinny zawierać zbyt szczegółowych informacji, ponieważ ich wartości mogą się zmieniać w zależności od tego, jak skrypty działają na dane, lub od decyzji podjętych przez przyszłych administratorów. Na przykład zmienna z pierwotnym identyfikatorem miles
może wymagać późniejszej zmiany na wartość w kilometrach, co spowoduje konieczność zmiany przez konserwatorów wszystkich odwołań do tej zmiennej, aby uniknąć przyszłych nieporozumień. Aby temu zapobiec, użyj zamiast tego identyfikatora distance
.
JavaScript nie przyznaje żadnych specjalnych uprawnień ani znaczeń identyfikatorom, które zaczynają się od znaku podkreślenia (_
). Znaki te są jednak zwykle używane, aby pokazać, że zmienna, metoda lub właściwość jest „prywatna”, co oznacza, że jest przeznaczona do użytku tylko w kontekście obiektu, który ją zawiera, i nie można jej modyfikować ani uzyskiwać do niej dostępu poza tym kontekstem. Jest to konwencja zapożyczona z innych języków programowania i poprzedza dodanie właściwości prywatnych w JavaScript.
Deklaracja zmiennej
Identyfikator można udostępnić JavaScript na kilka sposobów. Proces ten nazywa się „deklarowaniem” zmiennej. Zmienna jest deklarowana za pomocą słów kluczowych let
, const
lub var
.
let myVariable;
Aby zadeklarować zmienną, którą można zmienić w dowolnym momencie, użyj instrukcji let
lub var
. Te słowa kluczowe informują interpreter JavaScript, że ciąg znaków jest identyfikatorem, który może zawierać wartość.
Podczas pracy z nowoczesnym kodem źródłowym używaj tagu let
zamiast var
. var
nadal działa w nowoczesnych przeglądarkach, ale ma pewne nieintuicyjne zachowania zdefiniowane w najstarszych wersjach JavaScriptu, których nie można było później zmienić, aby zachować zgodność wsteczną. W ES6 dodano funkcję let
, aby rozwiązać niektóre problemy z projektowaniem var
.
Zmienna zadeklarowana jest inicjowana przez przypisanie jej wartości. Aby przypisać lub zmienić wartość zmiennej, użyj pojedynczego znaku równości (=
). Możesz to zrobić w ramach tego samego instruktażu, który go deklaruje:
let myVariable = 5;
myVariable + myVariable
> 10
Możesz też zadeklarować zmienną za pomocą let
(lub var
) bez jej inicjalizacji. Jeśli tak, początkowa wartość zmiennej to undefined
, dopóki kod nie przypisze jej wartości.
let myVariable;
myVariable;
> undefined
myVariable = 5;
myVariable + myVariable
> 10
Zmienna o wartości undefined
różni się od nieokreślonej zmiennej, której identyfikator nie został jeszcze zadeklarowany. Odwoływanie się do zmiennej, która nie została zadeklarowana, powoduje błąd.
myVariable
> Uncaught ReferenceError: myVariable is not defined
let myVariable;
myVariable
> undefined
Powiązanie identyfikatora z wartością jest zwykle nazywane „wiązaniem”.
Składnia występująca po słowach kluczowych let
, var
lub const
nazywana jest „listą wiązania” i umożliwia łączenie wielu deklaracji zmiennych rozdzielanych przecinkami (zakończonych oczekiwanym średnikiem). Dzięki temu te fragmenty kodu są funkcjonalnie identyczne:
let firstVariable,
secondVariable,
thirdVariable;
let firstVariable;
let secondVariable;
let thirdVariable;
Przy ponownym przypisaniu wartości zmiennej nie używa się instrukcji let
(ani var
), ponieważ JavaScript wie już, że dana zmienna istnieje:
let myVariable = true;
myVariable
> true
myVariable = false;
myVariable
> false
Możesz przypisać zmiennym nowe wartości na podstawie ich dotychczasowych wartości:
let myVariable = 10;
myVariable
> 10
myVariable = myVariable * myVariable;
myVariable
> 100
Jeśli spróbujesz ponownie zadeklarować zmienną za pomocą let
w środowisku produkcyjnym, pojawi się błąd składni:
let myVariable = true;
let myVariable = false;
> Uncaught SyntaxError: redeclaration of let myVariable
Narzędzia programistyczne w przeglądarkach są bardziej liberalne w odniesieniu do ponownego zadeklarowania let
(i class
), więc w konsoli dewelopera możesz nie zobaczyć tego samego błędu.
Aby zachować zgodność ze starszymi przeglądarkami, var
zezwala na niepotrzebne ponowne deklarowanie bez błędów w dowolnym kontekście:
var myVariable = true;
var myVariable = false;
myVariable\
> false
const
Aby zadeklarować stałą, czyli typ zmiennej, który musi zostać natychmiast zainicjowany i którego wartości nie można już zmienić, użyj słowa kluczowego const
. Identyfikatory stałych wartości podążają za tymi samymi regułami co zmienne zadeklarowane za pomocą let
(i var
):
const myConstant = true;
myConstant
> true
Nie można zadeklarować stałej bez natychmiastowego przypisania jej wartości, ponieważ stałych nie można przypisać ponownie po utworzeniu, więc każda niezinicjalizowana stała będzie zawsze miała wartość undefined
. Jeśli spróbujesz zadeklarować stałą bez inicjalizacji, pojawi się błąd składni:
const myConstant;
Uncaught SyntaxError: missing = in const declaration
Próba zmiany wartości zmiennej zadeklarowanej za pomocą const
w sposób podobny do zmiany wartości zmiennej zadeklarowanej za pomocą let
(lub var
) powoduje błąd typu:
const myConstant = true;
myConstant = false;
> Uncaught TypeError: invalid assignment to const 'myConstant'
Jednak gdy stała jest powiązana z obiektem, właściwości tego obiektu można zmienić.
const constantObject = { "firstvalue" : true };
constantObject
> Object { firstvalue: true }
constantObject.secondvalue = false;
constantObject
> Object { firstvalue: true, secondvalue: false }
Stałe zawierające obiekt to niezmienne odwołania do zmiennych wartości danych. Chociaż samej stałej nie można zmienić, właściwości obiektu, do którego się odwołuje, można zmieniać, dodawać i usuwać:
const constantObject = { "firstvalue" : true };
constantObject = false
> Uncaught TypeError: invalid assignment to const 'constantObject'
Jeśli nie spodziewasz się, że zmienna zostanie przypisana ponownie, zalecamy ustawić ją jako stałą. Użycie const
informuje zespół programistów lub przyszłych administratorów projektu, aby nie zmieniać tej wartości, ponieważ mogłoby to naruszyć założenia kodu dotyczące sposobu jej użycia, np. że zmienna zostanie w końcu oceniona na podstawie oczekiwanego typu danych.
Zakres zmiennej
Zakres zmiennej to część skryptu, w której jest ona dostępna.
Poza zakresem zmiennej nie będzie ona zdefiniowana – nie jako identyfikator zawierający wartość undefined
, ale tak, jakby nie została zadeklarowana.
W zależności od tego, jakiego słowa kluczowego używasz do zadeklarowania zmiennej, oraz od kontekstu, w którym ją definiujesz, możesz ograniczyć zakres zmiennych do instrukcji bloku (zakres bloku), poszczególnych funkcji (zakres funkcji) lub całej aplikacji JavaScript (zakres globalny).
Zakres bloku
Każda zmienna zadeklarowana za pomocą let
lub const
jest ograniczona do najbliższego bloku kodu, co oznacza, że można uzyskać do niej dostęp tylko w ramach tego bloku. Próba uzyskania dostępu do zmiennej ograniczonej do bloku poza blokiem zawierającym powoduje ten sam błąd co próba uzyskania dostępu do nieistniejącej zmiennej:
{
let scopedVariable = true;
console.log( scopedVariable );
}
> true
scopedVariable
> ReferenceError: scopedVariable is not defined
Z punktu widzenia JavaScriptu zmienna ograniczona do bloku nie istnieje poza blokiem, który ją zawiera. Możesz na przykład zadeklarować stałą wewnątrz bloku, a potem zadeklarować inną stałą poza tym blokiem, która używa tego samego identyfikatora:
{
const myConstant = false;
}
const myConstant = true;
scopedConstant;
> true
Chociaż zadeklarowana zmienna nie może rozszerzać się do bloku nadrzędnego, jest dostępna dla wszystkich bloków podrzędnych:
{
let scopedVariable = true;
{
console.log( scopedVariable );
}
}
> true
Wartość zadeklarowanej zmiennej można zmienić w bloku potomnym:
{
let scopedVariable = false;
{
scopedVariable = true;
}
console.log( scopedVariable );
}
> true
Nową zmienną można zainicjować za pomocą funkcji let
lub const
w bloku potomnym bez błędów, 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ą var
są ograniczone do najbliższej funkcji, która je zawiera (lub do bloku statycznej inicjalizacji w klasie).
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
Tak samo jest po wywołaniu funkcji. Mimo że zmienna jest inicjowana podczas wykonywania funkcji, nadal jest niedostępna poza jej zakresem:
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, we wszystkich blokach i funkcjach oraz we wszystkich skryptach na stronie.
Chociaż może się to wydawać pożądaną wartością domyślną, zmienne, do których dostęp ma dowolna część aplikacji i które może modyfikować, mogą powodować niepotrzebne obciążenie lub nawet kolidować z innymi zmiennymi w aplikacji o tym samym identyfikatorze. Dotyczy to wszystkich skryptów JavaScript zaangażowanych w renderowanie strony, w tym bibliotek zewnętrznych i analityki użytkowników. Dlatego zalecamy, aby w miarę możliwości unikać zanieczyszczania zasięgu globalnego.
Każda zmienna zadeklarowana za pomocą var
poza funkcją nadrzędną lub za pomocą let
lub
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 zadeklarowania (czyli bez użycia var
, let
lub const
do jej utworzenia) powoduje, że staje się ona zmienną globalną, nawet jeśli została zainicjowana wewnątrz funkcji lub bloku. Zmienna utworzona za pomocą tego wzorca jest czasami nazywana „implikowaną zmienną globalną”.
function myFunction() {
globalVariable = "global";
return globalVariable
}
myFunction()\
> "global"
globalVariable\
> "global"
Podnoszenie zmienne
Deklaracje zmiennych i funkcji są przenoszone na początek ich zakresu, co oznacza, że interpreter JavaScript przetwarza każdą zmienną zadeklarowaną w dowolnym miejscu w skrypcie i przenosi ją na pierwszy wiersz obejmującego ją zakresu przed wykonaniem skryptu. Oznacza to, że można odwoływać się do zmiennej zadeklarowanej za pomocą funkcji var
, zanim zostanie ona zadeklarowana, bez wywołania błędu:
hoistedVariable
> undefined
var hoistedVariable;
Ponieważ hostowane jest tylko oświadczenie zmiennej, a nie jej inicjalizacja, zmienne, które nie zostały zadeklarowane w sposób jawny za pomocą instrukcji var
, let
lub const
, nie są podnoszone:
unhoistedVariable;
> Uncaught ReferenceError: unhoistedVariable is not defined
unhoistedVariable = true;
Jak już wspomniano wcześniej, zadeklarowanej, ale nieinicjowanej zmiennej przypisano wartość undefined
. Takie zachowanie dotyczy również zadeklarowanych zmiennych, ale tylko tych zadeklarowanych za pomocą instrukcji var
.
hoistedVariable
> undefined
var hoistedVariable = 2 + 2;
hoistedVariable\
> 4
To nieintuicyjne zachowanie jest w dużej mierze pozostałością po decyzjach projektowych podjętych w najstarszych wersjach JavaScriptu i nie można go zmienić bez ryzyka uszkodzenia istniejących witryn.
let
i const
rozwiązują ten problem, zwracając błąd, gdy próbujesz uzyskać dostęp do zmiennej przed jej utworzeniem:
{
hoistedVariable;
let hoistedVariable;
}
> Uncaught ReferenceError: can't access lexical declaration 'hoistedVariable' before initialization
Ten błąd różni się od błędu „hoistedVariable is not defined” (zmienna hoistedVariable nie jest zdefiniowana), który może wystąpić podczas próby uzyskania dostępu do niezdeklarowanej zmiennej. Ponieważ JavaScript przesunął zmienną, wie, że zostanie ona utworzona w danym zakresie. Zamiast udostępniać tę zmienną przed jej deklaracją z wartością undefined
, interpreter zwraca błąd.
Zmienne zadeklarowane za pomocą instrukcji let
lub const
(lub class
) istnieją w tzw. „czasowej martwej strefie” (ang. temporal dead zone, TDZ) od początku bloku zewnętrznego do punktu w kodzie, w którym są zadeklarowane.
Czasowa martwa strefa sprawia, że działanie funkcji let
jest dla autorów bardziej intuicyjne niż działanie funkcji var
. Jest to też kluczowe dla projektu const
. Stałe nie mogą być zmieniane, więc stała podniesiona do góry zakresu i przypisana do wartości domyślnej undefined
nie może zostać zainicjowana za pomocą wartości znaczącej.
Sprawdź swoją wiedzę
Jakimi znakami można zaczynać identyfikator?
Która metoda deklarowania zmiennej, której wartość może być zmieniana w dowolnym momencie, jest preferowana?