Zmienne i stałe. Typy danych w Javascript.

Zmienne: var, let, const

Zmienne to podstawowy mechanizm przechowywania danych w programie. W JavaScript zmienne deklarujemy za pomocą słów kluczowych var, let lub const. Każde z nich ma trochę inne właściwości i zasady działania:

  • var: historycznie jedyny sposób deklarowania zmiennych w JS (przed rokiem 2015). Zmienne zadeklarowane przez var mają zasięg funkcyjny lub globalny, co oznacza, że jeśli zadeklarujesz zmienną var wewnątrz funkcji, będzie ona dostępna w całej tej funkcji (ale nie poza nią), a jeśli poza jakąkolwiek funkcją – stanie się zmienną globalną. var pozwala też na ponowną deklarację tej samej zmiennej (co bywa źródłem błędów). Przykład:
 var x = 1; if (true) { 
     var x = 2; // to tak naprawdę ta sama zmienna x (zasięg funkcji lub globalny) 
     console.log(x); // wypisze 2 
 } 
 console.log(x); // też wypisze 2, bo blok if nie tworzy nowego zakresu dla var

W dzisiejszych czasach var jest rzadziej używany – zastąpiły go let i const – ale warto znać, bo w starych skryptach JS wciąż go spotkasz.

  • let: wprowadzony w ES6 (2015) sposób deklarowania zmiennych o zasięgu blokowym. Oznacza to, że zmienna zadeklarowana poprzez let istnieje tylko wewnątrz bloku { }, w którym ją umieszczono (lub całego skryptu, jeśli na najwyższym poziomie). Nie można dwukrotnie zadeklarować zmiennej o tej samej nazwie w tym samym bloku. let jest zalecanym sposobem deklaracji zmiennych, gdyż ogranicza ich zakres, co zmniejsza ryzyko niechcącego nadpisania wartości. Przykład:
 let y = 5; 
 if (true) {       let y = 10; // to inna zmienna y, istniejąca tylko w tym bloku if 
    console.log(y); // 10 }  console.log(y); // 5 (oryginalna zmienna y pozostała nietknięta)
  • const: również wprowadzony w ES6, służy do deklaracji stałych. Zmienna zadeklarowana jako const także ma zasięg blokowy jak let, ale dodatkowo nie można zmienić przypisanej do niej wartości (przynajmniej jeśli chodzi o proste typy). Próba ponownego przypisania do const spowoduje błąd. Np.:
 const PI = 3.14159; PI = 3.14; // BŁĄD: nie można zmienić wartości stałej

Ważna uwaga: jeśli const wskazuje na obiekt lub tablicę, sama referencja jest stała, ale zawartość obiektu/elementy tablicy można zmieniać. Czyli

 const osoba = { imie: "Jan" };

nie pozwoli przypisać osoba = 5, ale można zrobić osoba.imie = "Adam" wewnątrz tego obiektu.

Podsumowując: używaj let do zmiennych, których wartość będzie się zmieniać, a const do wartości stałych lub zmiennych, które nie powinny być ponownie przypisane. var generalnie nie jest zalecany, chyba że istnieje specjalna potrzeba lub pracujemy w starym kodzie. Ze względu na zasięg blokowy let/const oraz ich bardziej przewidywalne zachowanie, większość nowych projektów w JS trzyma się tej pary. Wiele stylów kodowania wręcz sugeruje, by domyślnie używać const, a tylko wtedy gdy potrzebujemy zmienność – użyć let​.

Podstawowe typy danych

JavaScript jest językiem dynamicznie typowanym, co oznacza, że zmienna może przechowywać wartość dowolnego typu i można jej przypisać inną wartość (nawet innego typu) w trakcie działania programu. Nie musimy deklarować typu zmiennej – interpreter sam rozpoznaje typ wartości przypisanej. To elastyczne podejście: ta sama zmienna może np. najpierw przechowywać liczbę, a potem string, i nie spowoduje to błędu (choć w praktyce należy uważać, by nie mieszać typów w niekontrolowany sposób).

Jakie są typy danych w JavaScript? Standard ECMAScript definiuje kilka podstawowych typów. Możemy podzielić je na typy proste (prymitywne) oraz typ złożony:

  • Liczby (number): reprezentują zarówno liczby całkowite, jak i zmiennoprzecinkowe. W JavaScript wszystkie liczby (poza BigInt) są typu number i są przechowywane w formacie 64-bitowego zmiennoprzecinkowego (IEEE 754). Przykłady: 42, 3.14, -0.5. Istnieją też specjalne wartości jak NaN (Not a Number) i Infinity/-Infinity. Nie ma osobnych typów dla int/float – to wszystko number. Do operacji arytmetycznych używamy zwykłych operatorów (+, -, *, /, %).
  • Napisy tekstowe (string): ciągi znaków ujęte w cudzysłowy (pojedyncze '...' lub podwójne "...") albo backticki `...` (te ostatnie tworzą szablony stringów pozwalające wstawiać zmienne). String może być pusty ("") lub bardzo długi, może zawierać dowolne symbole (w Unicode). Przykłady: "Hello", ' świat', `Wynik = ${x+y}`.
  • Wartości logiczne (boolean): przyjmują jedną z dwóch wartości: true (prawda) lub false (fałsz). Używane są w warunkach, pętlach i wszędzie tam, gdzie potrzebna jest ocena prawda/fałsz.
  • null: specjalna wartość oznaczająca brak wartości. W praktyce null często jest używany gdy chcemy świadomie wskazać, że „tu nic nie ma”. Np. zmienna może być null gdy nie została jeszcze zainicjalizowana konkretnym obiektem.
  • undefined: inna szczególna wartość, która oznacza, że zmienna została zdefiniowana, ale nie przypisano do niej jeszcze żadnej wartości. Każda nowo zadeklarowana zmienna (bez inicjalizacji) ma domyślnie wartość undefined. Przykład: jsKopiujEdytujlet z; console.log(z); // undefined, bo nic jeszcze nie przypisano
  • Obiekty (object): to typ złożony. Obejmuje wszystko, co nie jest żadnym z powyższych typów prymitywnych. Obiektem jest zarówno zwykła struktura klucz-wartość (literał obiektowy {}), jak i tablice, funkcje, daty, ekspresje regularne itd. Obiekty w JS można traktować jak dynamiczne słowniki/rekordy – mogą posiadać właściwości (pola) i metody. Np. obiekt osoba: jsKopiujEdytujlet osoba = { imie: "Jan", wiek: 30 }; console.log(osoba.imie); // "Jan" będzie typu object. Tablica [] jest również szczególnym przypadkiem obiektu (ma indeksy liczbowe jako klucze i specjalne właściwości, np. długość). Funkcje też są obiektami (tzw. obiekty funkcyjne), co jest istotne, bo można je przekazywać jak dane.
  • BigInt: to nowszy (dodany w ES2020) typ prymitywny służący do reprezentowania bardzo dużych liczb całkowitych, które nie mieszczą się w zwykłym typie number. BigInt zapisujemy jako liczba z literą n na końcu, np. 12345678901234567890n. Dla początkujących ten typ rzadko będzie potrzebny, ale warto wiedzieć, że istnieje, gdy operujemy na ogromnych liczbach (np. kryptografia).
  • Symbol: kolejny mniej typowy prymitywny typ (dodany w ES2015). Symbol to unikalna, niezmienialna wartość, często używana jako unikalny klucz w obiektach lub do tzw. symboli globalnych. Symbole tworzy się za pomocą Symbol("opis"). Na wczesnym etapie nauki raczej się z nimi nie spotkasz – to zaawansowany koncept, używany głównie we wnętrzu bibliotek czy do specjalnych przypadków (np. definiowanie własnego iteratora obiektu).

Zwykle w codziennym kodowaniu najczęściej operujemy na: number, string, boolean, null/undefined i object (w tym array)​. Typy BigInt i Symbol pojawiają się rzadziej. Warto jeszcze raz podkreślić: JavaScript jest dynamicznie typowany, co daje elastyczność, ale wymaga ostrożności. Możemy np. dodać liczbę do stringa, co spowoduje nie arytmetykę, a konkatenację (połączenie w string) – JS automatycznie konwertuje typy w niektórych sytuacjach. Przykład:

 let wynik = "2" + 3;   // wynik = "23" (3 zostaje zamienione na "3" i dopisane do "2")
 let suma  = "2" * 3;   // wynik = 6   ("2" zostaje zamienione na 2 i mnożenie działa)

Takie zachowanie może czasem zaskakiwać. Dlatego programując w JS, staramy się pilnować, jakiego typu dane przekazujemy do operacji, albo jawnie konwertować wartości (np. użyć Number("2") żeby string „2” zamienić na liczbę 2).