Zakres zmiennych, hoisting - co warto wiedzieć?

 | 
Fotografia eleganckiego wnętrza z białymi ścianami i srebrnymi drzwiami windy. Photo by Edwin Chen on Unsplash.

Koniec wakacji, czas brać się do roboty 🙂 W tym wpisie postaram się krótko i treściwie omówić zakres zmiennych i hoisting w JavaScript.

Zakres zmiennych

Zakres zmiennych w JavaScript, to temat nieco skomplikowany. Programista, który dopiero zaczyna swoją przygodę z JSem, może być w niemałym szoku próbując okiełznać tajniki sztuki.

for (var a = 0; a < 5; a++) {}
console.log(a); // 5

Na początek stwórzmy standardową pętlę for, w której deklarujemy zmienną a = 0. Poniżej odwołujemy się do tej zmiennej i jako rezultat dostajemy 5.

Wniosek: Deklaracja zmiennej poprzez słowo kluczowe var powoduje zalokowanie miejsca w pamięci i zachowanie stanu pomimo zakończenia pętli. Zmienna jest widoczna w kontekście funkcji.

Na ratunek let i const

W standardzie ECMAScript 2015 (ES6) wprowadzone zostały nowe słowa kluczowe let i const. Służą do tego samego co var, ale mają ograniczony zasięg.

let is the new var.

for (let a = 0; a < 5; a++) {}
console.log(a); // Uncaught ReferenceError: a is not defined

Jak widzimy w powyższym przykładzie, zamiana var na let daje wymierny skutek. Nie mamy dostępu do zmiennej poza blokiem for. O to nam chodziło... wykorzystujemy zmienną z kontekstu blokowego.

Jak się ma do tego const?

Deklaruje nazwaną stałą tylko do odczytu - MDN

Nie możemy ponownie przypisać wartości do const:

const a = 7;
a = 5; // Uncaught TypeError: Assignment to constant variable.

Nie możemy też ponownie zadeklarować stałej:

const a = 7;
const a = 5; // Uncaught SyntaxError: Identifier 'a' has already been declared

JS ma jednak swoje wymagania, a const może sporadycznie piszących w tym języku wprowadzić w błąd.

const a = [];
console.log(a); // []
a.push(2);
console.log(a); // [2]
a.push({ a: 3 });
console.log(a); // [2, {a: 3}]

W JavaScript const NIE oznacza deklaracji stałej wartości, lecz deklarację stałej referencji. W przypadku typów prymitywnych const zachowuje się tak jak oczekujemy. Przy typach złożonych mamy możliwość podmiany zawartości.

Idealnie obrazuje to przykład powyżej. Tworzymy stałą a = [], następnie poprzez metodę push dodajemy pierwszy element tablicy, itd.

Hoisting

Temat hoistingu jest często poruszany, zarówno na branżowych spotkaniach jak i rozmowach kwalifikacyjnych. To jeden z feature'ów JSa, o którym wszyscy słyszeli lub wkrótce usłyszą.

Hoisting, spolszczona nazwa windowanie, to mechanizm pozwalający na przeniesienie deklaracji zmiennych oraz metod na początek funkcji.

a = 5;
var a;
console.log(a); // 5

i

simpleFunction(); // hoisting

function simpleFunction() {
  console.log('hoisting');
}

W przykładzie pierwszym do zmiennej a przypisujemy 5, następnie ją deklarujemy. Log w konsoli daje rezultat 5. Drugi przykład, to wywołanie metody przed deklaracją. Rezultat taki sam jak wcześniej. Hoisting zadziałał.

Przy deklaracji zmiennych za pomocą słowa kluczowego let, hoisting zachowuje się bardziej przewidywalnie.

a = 5;
let a; // ReferenceError: a is not defined

Strict mode

Strict mode (tryb ścisły) to jeden z feature'ów ES5. Wprowadza kilka zmian do domyślnej semantyki JavaScript:

  1. Pozwala wyeliminować ciche błędy (ang. silent errors).
  2. Pozwala wyeliminować błędy, które uniemożliwiają optymalizację JSa przez przeglądarki.
  3. Uniemożliwia stosowanie składni mogącej wystąpić w kolejnych odsłonach ECMAScript.

Temat został pobieżnie wywołany, przy okazji hoistingu, nie bez przyczyny. Strict mode nie zezwala na skorzystanie ze zmiennej, dopóki nie zostanie zadeklarowana.

Źródła


Profile picture

Dawid Ryłko
Github | Twitter | Linkedin

Copyright © 2024 Dawid Ryłko