JavaScript: let, var, const - wybierz właściwie!

Wojciech Sokołowski .

15 maja 2026

Porównanie `var`, `let` i `const` w `js`. `var` to pudełko, `let` to pudełko z tarczą, `const` to klatka.

W JavaScript let służy do deklarowania zmiennych, których wartość może się zmieniać, ale tylko wewnątrz konkretnego bloku kodu. To drobna różnica składniowa, która w praktyce mocno wpływa na czytelność, porządek w stanie aplikacji i liczbę trudnych do znalezienia błędów. W tym tekście pokazuję, jak działa zakres blokowy, czym let różni się od var i const oraz kiedy naprawdę warto go używać w projektach webowych.

Najważniejsze zasady używania zmiennych blokowych w JavaScript

  • let tworzy zmienną z zakresem blokowym, więc działa tylko wewnątrz najbliższego bloku.
  • Warto po niego sięgać wtedy, gdy wartość ma się zmieniać, ale nie powinna wychodzić poza dany fragment kodu.
  • W porównaniu z var daje mniej zaskoczeń, bo nie przecieka poza blok i szybciej ujawnia błędy.
  • Nie można go bezpiecznie odczytać przed deklaracją, bo wchodzi wtedy w temporal dead zone.
  • Jeśli zmienna nie będzie nadpisywana, zwykle lepszy jest const.

Co naprawdę robi let w JavaScript

Najprościej: let deklaruje lokalną zmienną, którą można przypisać ponownie. To ważne rozróżnienie, bo sama nazwa nie mówi jeszcze nic o czasie życia wartości. Liczy się zakres, a przy let jest on blokowy, czyli ograniczony do miejsca otoczonego klamrami.

let licznik = 0;
licznik += 1;

W praktyce traktuję let jako narzędzie do krótkich, kontrolowanych zmian stanu. Jeśli deklaruję go wewnątrz bloku, to poza tym blokiem nie istnieje. To pomaga zamykać logikę tam, gdzie faktycznie jest potrzebna, zamiast rozlewać ją po całej funkcji lub całym pliku.

Na poziomie globalnym let nie dopisuje też zmiennej do obiektu globalnego w taki sposób jak stare deklaracje, więc mniej ryzykuję przypadkowe kolizje z innym skryptem na stronie. To prowadzi wprost do pytania, gdzie ten blok ma największe znaczenie.

Diagram przedstawia scope w JS: var (function), let (block), const (block).

Gdzie zakres blokowy robi różnicę

Zakres blokowy oznacza, że zmienna żyje tylko w obrębie klamr, w których została zadeklarowana. W praktyce najbardziej czuć to w warunkach, pętlach i małych blokach pomocniczych, które wyraźnie oddzielają jedną część logiki od drugiej.

Pętle i liczniki

To klasyczny przypadek. Jeśli licznik ma działać tylko wewnątrz pętli, let sprawdza się naturalnie, bo każda iteracja może mieć własny stan albo własną wartość pomocniczą.

for (let i = 0; i < buttons.length; i++) {
  buttons[i].addEventListener("click", () => {
    console.log(`Kliknięto przycisk nr ${i + 1}`);
  });
}

To jeden z tych przykładów, które realnie pomagają w kodzie front-endowym. W starszych wzorcach z var łatwo o efekt, w którym wszystkie callbacki widzą tę samą, końcową wartość. Przy formularzach, przyciskach i elementach koszyka sklepu internetowego takie błędy potrafią być wyjątkowo irytujące.

Warunki i bloki pomocnicze

Gdy tworzę zmienną tylko po to, by przetworzyć wynik w jednym if albo wewnątrz małego fragmentu formularza, nie chcę jej trzymać dłużej niż trzeba. Dzięki temu kod jest krótszy mentalnie: czytam blok i wiem, że wszystko, co w nim powstało, kończy się razem z nim.

if (hasDiscount) {
  let finalPrice = basePrice - discount;
  renderPrice(finalPrice);
}

Takie podejście szczególnie dobrze działa w interfejsach, gdzie mamy krótkie operacje na stanie: walidację pola, policzenie rabatu, zmianę etapu checkoutu albo przygotowanie danych do wysłania.

switch i try/catch bez zaskoczeń

W switch warto uważać, bo to nadal jeden blok. Jeśli deklaruję tam let, zwykle dodaję osobne klamry dla konkretnego case’a. W try/catch też najlepiej myśleć o zasięgu dosłownie: to, co służy tylko obsłudze błędu, nie powinno wychodzić poza ten fragment.

switch (status) {
  case "paid": {
    let label = "Opłacone";
    console.log(label);
    break;
  }
}

Właśnie dlatego zakres blokowy jest tak praktyczny: ogranicza życie zmiennej do miejsca, w którym naprawdę jest potrzebna. Gdy to rozumiesz, porównanie z innymi deklaracjami przestaje być teoretyczne.

Różnice między let, const i var

Jeśli miałbym uprościć wybór do jednej zasady, to zwykle zaczynam od const, a dopiero gdy wiem, że wartość będzie się zmieniać, przechodzę na let. var zostawiam głównie przy starym kodzie albo wtedy, gdy muszę utrzymać zgodność z bardzo dawnymi fragmentami projektu.

Cecha let const var
Zakres blokowy blokowy funkcji lub skryptu
Możliwość przypisania ponownie tak nie tak
Ponowna deklaracja w tym samym zakresie nie nie tak, i to bywa zdradliwe
Najlepsze zastosowanie zmienne robocze, liczniki, stany przejściowe wartości stałe, referencje, konfiguracja starsze projekty i wsteczna zgodność

Z takiego zestawienia płynie prosty wniosek: nie używam let „na wszelki wypadek”. Używam go wtedy, gdy zmienna ma się zmieniać, ale nadal powinna być zamknięta w konkretnym zakresie. Jeżeli w ogóle nie ma się zmieniać, const jest zwykle czytelniejszy i bezpieczniejszy. Warto też pamiętać, że przy obiektach const blokuje ponowne przypisanie referencji, a nie samą mutację wnętrza obiektu.

To właśnie w tym miejscu pojawiają się najczęstsze błędy, bo sama składnia nie chroni przed złym założeniem o zakresie.

Najczęstsze błędy i pułapki z let

Odczyt przed deklaracją

Najbardziej zdradliwy problem to próba użycia zmiennej przed jej deklaracją. W przypadku let nie dostaniesz po prostu pustej wartości. Najczęściej kończy się to błędem ReferenceError, bo zmienna znajduje się w temporal dead zone, czyli w okresie między wejściem do bloku a faktyczną deklaracją.

{
  console.log(total);
  let total = 0;
}

To nie jest drobiazg teoretyczny. W większych plikach łatwo go przeoczyć, zwłaszcza gdy logika jest rozbita na kilka funkcji albo warunków. Ja traktuję to jako sygnał, że kod wymaga lepszego uporządkowania, a nie tylko „poprawienia jednej linijki”.

Redeklaracja w tym samym zakresie

let nie pozwala zadeklarować tej samej nazwy dwa razy w jednym zakresie. To dobra rzecz, bo szybciej wykrywa bałagan, ale bywa zaskoczeniem przy kopiowaniu fragmentów kodu albo przy refaktorze. Jeśli próbuję powtórzyć nazwę, interpreter zatrzyma mnie od razu, zamiast pozwolić na ciche nadpisanie.

Przeczytaj również: background-clip w CSS - jak precyzyjnie malować tło?

Shadowing, czyli zasłanianie nazw

Da się zadeklarować zmienną o tej samej nazwie w wewnętrznym bloku, ale to nie zawsze jest dobry pomysł. Technicznie działa, jednak potrafi utrudnić debugowanie, bo w danym miejscu kodu widzę inną wartość niż ta, którą mam w głowie.

let price = 120;

if (discountActive) {
  let price = 99;
  console.log(price);
}

Takie rozwiązanie ma sens tylko wtedy, gdy różne zakresy naprawdę opisują różne etapy obliczeń. Jeśli nie, wolę inną nazwę zamiast liczyć na to, że po chwili sam nie pomylę lokalnej wersji z zewnętrzną.

Najkrócej: let jest bezpieczniejszy niż var, ale nie zwalnia z dyscypliny. Jeśli zmienna ma żyć tylko chwilę, ogranicz jej zakres; jeśli nie potrzebujesz zmienności, nie wymuszaj jej na siłę. To dobry moment, żeby przejść z zasad na praktykę w kodzie webowym.

Jak używać let w kodzie webowym, żeby nie zaciemniać logiki

W projektach front-endowych zwykle używam let do trzech rzeczy: stanów przejściowych, liczników i tymczasowych wyników obliczeń. To są przypadki, w których wartość może się zmieniać, ale tylko przez krótki odcinek życia funkcji albo komponentu.

  • Krok formularza - gdy użytkownik przechodzi przez checkout albo wieloetapowy formularz, zmienna typu let currentStep = 1; ma sens, bo krok faktycznie się zmienia.
  • Indeks w pętli - przy iteracji po elementach DOM albo przy budowaniu listy produktów let pozwala zachować porządek w logice i w callbackach.
  • Tymczasowy wynik - jeśli coś liczę, waliduję albo normalizuję i wynik może się zmienić w trakcie przetwarzania, let jest naturalnym wyborem.
let currentStep = 1;

nextButton.addEventListener("click", () => {
  currentStep += 1;
  renderStep(currentStep);
});

W praktyce bardzo pomaga mi jedna zasada robocza: jeśli po pierwszym przypisaniu wartość już się nie zmienia, zamieniam let na const. Dzięki temu kod pozostaje spójny, a osoba czytająca go po mnie nie musi zgadywać, czy dana zmienna była naprawdę zmienna, czy tylko ktoś zostawił ją z rozpędu.

W kodzie sklepu internetowego, panelu administracyjnego czy formularza kontaktowego taka konsekwencja robi większą różnicę niż kolejne mikrooptymalizacje. To prowadzi do prostego wniosku o tym, co naprawdę warto zapamiętać.

Dlaczego blokowy zasięg ułatwia porządek w interfejsach i sklepach

Jeśli miałbym zostawić tylko jedną radę, byłaby prosta: najpierw myśl o czasie życia zmiennej, dopiero potem o samej składni. let jest dobry wtedy, gdy wartość rzeczywiście się zmienia, a jednocześnie chcesz ograniczyć ją do jednego bloku, funkcji albo pętli.

W 2026 to bezpieczny, standardowy wybór w nowym kodzie webowym. Najwięcej zysku daje nie sam fakt użycia let, ale konsekwencja: krótkie zakresy, brak nadmiarowych deklaracji i świadome sięganie po const, gdy zmienność nie jest potrzebna. Tak właśnie kod staje się prostszy do utrzymania, zwłaszcza gdy projekt rośnie i przechodzi przez kilka etapów rozwoju.

Jeżeli pamiętasz tylko jedną rzecz, niech będzie to ta: zasięg zmiennej powinien być tak mały, jak to możliwe, ale tak duży, jak to konieczne.

FAQ - Najczęstsze pytania

Główna różnica to zakres. let ma zakres blokowy (zmienna żyje tylko w klamrach, gdzie została zadeklarowana), podczas gdy var ma zakres funkcyjny lub globalny, co może prowadzić do nieoczekiwanych zachowań i błędów.
Używaj let, gdy wartość zmiennej będzie się zmieniać (np. liczniki, stany przejściowe). Używaj const, gdy zmienna przechowuje stałą wartość lub referencję, która nie będzie nadpisywana. Preferuj const dla większej czytelności i bezpieczeństwa.
Nie, nie możesz redeklarować zmiennej zadeklarowanej za pomocą let w tym samym zakresie. Próba takiej operacji spowoduje błąd. To pomaga uniknąć przypadkowego nadpisywania zmiennych i poprawia jakość kodu.
"Temporal dead zone" (TDZ) to okres między wejściem do bloku kodu a faktyczną deklaracją zmiennej let. Próba użycia zmiennej w TDZ spowoduje błąd ReferenceError, ponieważ zmienna nie jest jeszcze zainicjowana.
let jest bardzo przydatny w pętlach (np. for), gdzie każda iteracja potrzebuje własnego, niezależnego licznika, oraz w blokach warunkowych (if), gdzie zmienne są potrzebne tylko tymczasowo. Pomaga to unikać wycieków zmiennych i utrzymywać porządek w logice interfejsu użytkownika.
Oceń artykuł

Średnia: 0.0 / 5 · 0 ocen

Tagi

let js let var const różnice zasięg let w javascript
Autor Wojciech Sokołowski
Wojciech Sokołowski
Nazywam się Wojciech Sokołowski i od 15 lat zajmuję się tworzeniem stron internetowych, e-commerce oraz SEO. Moje zainteresowanie tymi dziedzinami zaczęło się od potrzeby zrozumienia, jak technologie mogą wspierać rozwój biznesu w internecie. Lubię dzielić się wiedzą na temat skutecznych strategii marketingowych oraz optymalizacji stron, ponieważ wiem, jak ważne jest, aby każdy mógł odnaleźć się w złożonym świecie online. W swojej pracy skupiam się na dostarczaniu rzetelnych i przystępnych informacji. Staram się porównywać różne źródła, aby zapewnić moim czytelnikom aktualne i użyteczne treści. Zawsze dążę do tego, aby skomplikowane zagadnienia były jasne i zrozumiałe, co pozwala mi pomagać innym w skutecznym wykorzystaniu potencjału internetu.
Komentarze (0)
Dodaj komentarz