CODELIVERY BLOG

JavaScript: let vs var – różnice i kiedy używać którego

utworzone przez | lis 5, 2025 | Bez kategorii

Best Asset management alternatives in 2024

Spis Treści

Let i var to dwa sposoby deklarowania zmiennych w JavaScript, które różnią się fundamentalnie pod względem zasięgu (scope), hoistingu i możliwości ponownej deklaracji. Wprowadzenie let w ES6 (2015) było odpowiedzią na problemy i nieintuicyjne zachowania var, które przez lata frustraowały programistów i prowadziły do trudnych do znalezienia bugów.

Dla developerów uczących się JavaScript lub migrujących legacy code do nowoczesnych standardów, zrozumienie różnic między let a var jest kluczowe dla pisania czystego, przewidywalnego kodu bez subtelnych błędów związanych z zakresem zmiennych.

Zasięg (Scope) – fundamentalna różnica

Var ma zasięg funkcyjny (function scope), co oznacza, że zmienna jest widoczna w całej funkcji, niezależnie od bloku w którym została zadeklarowana. Nawet jeśli zadeklarujesz var wewnątrz pętli for czy bloku if, będzie dostępna poza tym blokiem, ale tylko w ramach funkcji.

javascript

function testVar() {
    if (true) {
        var x = 10;
    }
    console.log(x); // 10 - działa!
}

Let ma zasięg blokowy (block scope), co jest bardziej intuicyjne i zgodne z większością innych języków programowania. Zmienna zadeklarowana z let istnieje tylko w bloku, w którym została utworzona – wewnątrz {}.

javascript

function testLet() {
    if (true) {
        let y = 10;
    }
    console.log(y); // ReferenceError: y is not defined
}

To zachowanie let eliminuje całą klasę bugów związanych z niezamierzonym wyciekaniem zmiennych poza ich logiczny kontekst.

Hoisting – wyciąganie deklaracji

Var jest hoistowany – deklaracja jest przenoszona na początek funkcji podczas kompilacji, ale inicjalizacja pozostaje w miejscu. To prowadzi do sytuacji, gdzie można odwoływać się do zmiennej przed jej deklaracją, otrzymując undefinedzamiast błędu.

javascript

console.log(a); // undefined (nie błąd!)
var a = 5;
console.log(a); // 5

Let też jest hoistowany, ale znajduje się w „temporal dead zone” od początku bloku do momentu deklaracji. Odwołanie przed deklaracją powoduje ReferenceError.

javascript

console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 5;
console.log(b); // 5

Temporal dead zone wymusza deklarowanie zmiennych przed ich użyciem, co jest dobrą praktyką programistyczną i zapobiega subtelnym błędom.

Ponowna deklaracja

Var pozwala na ponowną deklarację tej samej zmiennej w tym samym zasięgu bez błędu. To może prowadzić do przypadkowego nadpisywania zmiennych.

javascript

var name = "Jan";
var name = "Anna"; // działa, nadpisuje bez ostrzeżenia
console.log(name); // "Anna"

Let nie pozwala na ponowną deklarację w tym samym zasięgu, rzucając błąd składni. To chroni przed przypadkowym nadpisaniem.

javascript

let name = "Jan";
let name = "Anna"; // SyntaxError: Identifier 'name' has already been declared

Możesz jednak ponownie przypisać wartość do zmiennej let (reassignment), co jest różne od re-declaration:

javascript

let name = "Jan";
name = "Anna"; // OK - reassignment

Pętle i zamknięcia (closures)

Var w pętlach tworzy jedną współdzieloną zmienną dla wszystkich iteracji, co prowadzi do słynnego problemu z setTimeout:

javascript

for (var i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 100);
}
// Wypisze: 3, 3, 3 (nie 0, 1, 2!)

Let w pętlach tworzy nową zmienną dla każdej iteracji, co rozwiązuje problem:

javascript

for (let i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 100);
}
// Wypisze: 0, 1, 2 (jak oczekiwano)

To zachowanie let eliminuje potrzebę IIFE (Immediately Invoked Function Expression) czy innych workarounds używanych z var.

Zmienne globalne i window object

Var w scope globalnym tworzy właściwość obiektu window w przeglądarce:

javascript

var globalVar = "test";
console.log(window.globalVar); // "test"

Let w scope globalnym nie dodaje właściwości do window:

javascript

let globalLet = "test";
console.log(window.globalLet); // undefined

To zapobiega przypadkowemu zanieczyszczaniu globalnej przestrzeni nazw i konfliktom z właściwościami window.

Gemini Generated Image tujo10tujo10tujo
JavaScript: let vs var - różnice i kiedy używać którego 2

Kiedy używać którego

Zawsze używaj let (lub const) w nowoczesnym JavaScript. ES6+ best practices zalecają:

  • const jako default dla wartości, które nie będą reassignowane
  • let dla zmiennych, które będą reassignowane
  • var praktycznie nigdy w nowym kodzie

Legacy code może wymagać używania var dla kompatybilności z bardzo starymi przeglądarkami (pre-2015), ale transpilery jak Babel pozwalają pisać nowoczesny kod z let/const kompilując do var dla starych środowisk.

Linting i Code Quality – ESLint z regułami no-var i prefer-const wymusza nowoczesne praktyki, automatycznie flagując użycie var jako code smell.

Migracja z var do let/const

Przy refaktoringu legacy code:

  1. Zamień wszystkie var na let
  2. Przetestuj dokładnie – zmiany w scope mogą ujawnić ukryte bugi
  3. Zmień let na const wszędzie gdzie możliwe
  4. Uruchom testy jednostkowe i integracyjne

Automatyczne narzędzia jak ESLint z --fix mogą pomóc, ale ręczna weryfikacja jest kluczowa dla critical code.

Wprowadzenie let i const w ES6 było jedną z najważniejszych poprawek JavaScript, eliminując źródło niezliczonych bugów i frustracji. Dla każdego współczesnego projektu JavaScript, var powinien być traktowany jako przestarzały, a letconst jako standard. Block scope, temporal dead zone i zakaz re-declaration czynią kod bardziej przewidywalnym i łatwiejszym w utrzymaniu.


Bibliografia:

  1. „You Don’t Know JS: Scope & Closures” – Kyle Simpson (2014)
  2. „JavaScript: The Definitive Guide, 7th Edition” – David Flanagan (2020)
  3. MDN Web Docs – „let” – https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
  4. MDN Web Docs – „var” – https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
  5. „Exploring ES6” – Dr. Axel Rauschmayer (2015)
  6. ECMAScript 2015 Language Specification – https://www.ecma-international.org/ecma-262/6.0/
  7. ESLint Documentation – „no-var” rule – https://eslint.org/docs/rules/no-var

Let’s deliver great things together.

Reach out to discuss your next big idea.

Get in Touch: Leave Your Message Here!

In 2012, I invested in a project led by Marek and Dominik. Throughout the investment period, the company demonstrated creativity, and their pivots were successfully implemented by the team.

Rafał Brzoska

CEO at InPost

Agreement