search check home clock-o tag tags chevron-left chevron-right chevron-up chevron-down twitter facebook github rss comment comments terminal code

[JS] ECMAScript 6 – jaka jest różnica między var i let?

[JS] ECMAScript 6 – jaka jest różnica między var i let?

Nowy standard pisania kodu JavaScript, ECMAScript 6 - wprowadzony już jakiś czas temu, do tej pory nie jest jeszcze dobrze rozumiany przez webdeveloperów. Wprowadza dużo ciekawych zmian, między innymi konstrukcję let, która jest odpowiedzialna za deklarację zmiennych.

Różnica między let i var

Zasadniczo, różnica sprowadza się zasięgu w jakim zadeklarowana zmienna działa.

var
Zmienne zadeklarowane za pomocą var działają w kontekście funkcji.
let
Deklaracja zmiennej za pomocą let sprawia, że zmienna działa w kontekście blokowym, np. wewnątrz pętli.

Jeśli definicje powyżej niewiele Ci mówią, to postaram się to znacznie bardziej przybliżyć za pomocą przykładów poniżej.

Zmienne o zasięgu funkcyjnym

(function () {
  var letter = 'A';
  if (letter.length) {
    console.log(letter); // zwraca A
    var letter = 'B';
    console.log(letter); // zwraca B
  }
  console.log(letter); // zwraca B
})();

W powyższym przykładzie, zmienna letter na początku przyjmuje wartość A, następnie w instrukcji warunkowej if od nowa definiujemy zmienną letter i ustawiamy jej wartość na B. Wygląda to tak jakbyśmy od nowa deklarowali zmienną letter, ale tak naprawdę tylko modyfikujemy jej wartość. Nowa wartość zmiennej będzie widoczna w całej funkcji, dlatego przy drugim wywołaniu console.log() zmienna ma dalej wartość B.
Takie zachowanie zmiennych świadczy o zasięgu funkcyjnym.

Zmienne o zasięgu blokowym

(function () {
  let letter = 'A';
  if (letter.length) {
    console.log(letter); // zwraca undefined
    let letter = 'B';
    console.log(letter); // zwraca B
  }
  console.log(letter); // zwraca A
})();

Przykład powyżej demonstruje działanie konstrukcji let. Jak można zauważyć, najpierw zdefiniowaliśmy zmienną letter i nadaliśmy jej wartość A. Następnie w if od nowa definujemy zmienną letter i nadajemy jej wartość B. Jak można zauważyć console.log() w każdym bloku zwraca inną wartość. Wartość zmiennej w instrukcji if nie nadpisuje wartości zmiennej zdeklarowanej wcześniej, w bloku wyżej.
Takie zachowanie demonstruje główną różnicę w działaniu konstrukcji let i var.

Działanie var i let jednocześnie

Nic nie stoi na przeszkodzie, aby wykorzystać obydwie konstrukcje jednocześnie w tym samym kawałku kodu.

1
2
3
4
5
6
7
8
9
10
11
(function () {
  var letter = 'A';
 
  if (letter.length) {
    console.log(letter); // zwraca A
    let letter = 'B';
    console.log(letter); // zwraca B
  }
 
  console.log(letter); // zwraca A
})();

Jak widać, działanie obydwu wersji zmiennej pozostało niezakłócone. Zmienna zadeklarowana za pomocą var, zachowuje swoją wartość w zasięgu całej funkcji, a zmienna zadeklarowana za pomocą let przyjmuje nową wartość tylko w zasięgu wybranego bloku (między klamrami). Dzięki temu można tworzyć tymczasowe zmienne, niezależne od wartości zmiennych w szerszym kontekście.

Podsumowanie

Mam nadzieję, że udało mi się wyjaśnić w sposób przejrzysty różnicę między let i var, dzięki czemu będziesz mógł w sposób pełni świadomy korzystać z możliwości takiej deklaracji zmiennych.

Różnica między let i var

Różnica polega na różnym zasięgu działania tak zadeklarowanej zmiennej. Konstrukcja var działa w kontekście funkcji, a let w kontekście bloku kodu.

Nowy standard JavaScript daje niesamowite możliwości zarządzania swoim kodem oraz możliwość ograniczenia liczby tworzonych zmiennych potrzebnych do działania zastosowanych mechanizmów. Niestety, w chwili obecnej stosowanie nowego standardu ECMAScript 6, w kodzie pisanym na potrzeby przeglądarek internetowych, nie ma sensu. Natomiast, jeśli piszesz kod dla platformy node.js, to jak najbardziej możesz zacząć korzystać z dobrodziejstw tego standardu.

  • >Nowy standard pisania kodu JavaScript, ECMAScript 6 – wprowadzony już jakiś czas temu, do tej pory nie jest jeszcze dobrze rozumiany przez webdeveloperów.
    IMO nie jest wprowadzony, bo specka wciąż nie ma statusu finalnej. A nawet jakby miała, to przecież nie ma żadnej sensownej implementacji 😉

    >Natomiast, jeśli piszesz kod dla platformy node.js, to jak najbardziej możesz zacząć korzystać z dobrodziejstw tego standardu.
    też nie tak do końca. stabilny node nie ma dużo features z ES6 a nawet jak ma, to potrzebuje flagi –harmony do działania

    Brakuje mi wzmianki o const, które zachowuje się jak let, tyle, że nie da się zmienić wartości 😉 inna rzecz – dziwi mnie, że stałe są blokowe

    co do ES6 i browserów, ciekawi mnie jeszcze inna rzecz – jak TC39 chce zapewnić BC (no bo zapewnić musi)

  • Marek

    Dla mnie ma sens że stałe są blokowe. Widać chcą się wycofać z błędu jakim było przyjęcie zasięgu funkcyjnego dla var.

  • no właśnie nie ma sensu, bo stałe były w lisku od jakichś dobrych 3 lat i miały zasięg funkcyjny…
    miałoby to sens gdyby faktycznie wycofali się z funkcyjnego zasięgu dla var, ale jest to po prostu niemożliwe – dlatego wgl powstał taki byt jak let. skoro JS ma domyślnie zasięg funkcyjny, to tego bym się trzymał a nie wprowadzał niepotrzebne zamieszanie.
    inna rzecz, że jak dla mnie stałe blokowe są po prostu mało przydatne – nie użyję ich choćby do zdefiniowania głównych ustawień dla skryptu, bo… po prostu nie będą widoczne.

  • Marek

    Zasięg blokowy ma sens i fajnie że idą w jego stronę. Nie mogą sobie pozwolić jednocześnie na to żeby cała masa skryptów przestała działać bo nagle wyłączą wsparcie dla „var”.

    A że zmienne sobie zdefiniujesz w bloku nadrzędnym nie wyklucza przecież tego że będą one widoczne w blokach podrzędnych. Pod warunkiem oczywiście że sobie ich nie przysłonisz zmiennymi lokalnymi o takich samych nazwach.

  • no właśnie o to chodzi – JS od zawsze był językiem z zasięgiem funkcyjnym i dlatego nie powinno się tego ruszać w tak chamski sposób. może nie jest to idealny rodzaj zasięgu, ale się przecież sprawdza.
    a takie let nagle nie dość, że blokowe, to np dodatkowo nie podlega hoistingowi. czyli robimy JS bez JS tak naprawdę

    co do bloku nadrzędnego – ok, ale ta deklaracja wciąż musi być w tym bloku nadrzędnym. a czasami chcemy mieć coś (pseudo)globalnego, co dodatkowo będzie read-only (i nie chcemy się babrać z dziwnymi rzeczami typu Object.freeze)

  • Marek

    Trzeba iść naprzód. Zwłaszcza że pomimo że bardzo lubię javascript to jest on językiem mocno posranym 🙂 Nie rozumiem w czym widzisz problem. Moim zdaniem można dobrze pogodzić let oraz var w jednym kodzie programu.

    pseudo globalnego ? Możesz podać jakiś przykład kodu o co Ci chodzi ? Dalej twierdzę że można ładnie pogodzić let i var i z tym też nie powinno być problemu.

  • owszem, można pogodzić let z var, tylko po co? przez 10 lat z okładem nikt specjalnie nie cierpiał z powodu braku zasięgu blokowego 😉 zastosowanie let widzę tylko dla pętli

    co do pseudoglobalnego, myślałem po prostu o wywaleniu kilku stałych na początek kodu programu i odwoływaniu się do nich w reszcie kodu. bo dla mnie blokowy const nie ma sensu za bardzo – jego zakres występowania jest cholernie wąski i równie dobrze można wówczas użyć let

  • Wg mnie let jest warty wykorzystania w momencie gdy pojawi się problem z nazwaniem zmiennej w sensowny sposób, a która to już nazwa została użyta wcześniej z wykorzystaniem var. Wtedy nie nadpisujemy poprzednich wartości z vara a jedynie tymczasowo użyczamy sobie nazwę zmiennej.

  • Tommy Lee Jones

    „The let block and let expression syntax is non-standard and will be removed in the future. Do not use them!”
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Non-standard_let_extensions

  • Interesujące. Dziękuję za informację.