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
-
lettworzy 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
vardaje 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.

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
letpozwala 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,
letjest 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.