Přejít k navigační liště

Zdroják » JavaScript » Rozdíl mezi var a let v JavaScriptu

Rozdíl mezi var a let v JavaScriptu

Články JavaScript

Ukážeme si, jaký je v JavaScriptu rozdíl mezi deklarováním proměnných přes var a let.

Text vyšel původně na autorově webu.

Proměnné lze v JS používat různým způsobem. Čím se tyto způsoby liší?

Objekt window

a = 1;
var b = 2;
let c = 3;

Jsou-li proměnné deklarovány takto, jediný rozdíl z pohledu window objektu je, že deklarace přes let se nedostane do objektu window:

console.log(window.a); // 1
console.log(window.b); // 2
console.log(window.c); // undefined

Pořadí deklarace

V angličtině se pro to používá termín hoisting (šlo by přeložit možná jako zvednutí).

V JS je možné deklarovat proměnné či funkce později v kódu, než je používat:

a(); // a

function a() {
    console.log('a')
}

Stejně tak proměnné pomocí var:

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

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

Proměnné ale nesmí být inicializované, musí být pouze deklarované (tj. bez přiřazení hodnoty):

console.log(a) // undefined
var a = 2;

Scope/closure

Tato dvě anglická slova se překládají jako „rozsah platnosti“ a „uzávěra“.

Lidsky řečeno definují oblasti kódu, kde jsou proměnné dostupné.

var a = 1;

function b() {
    console.log(a)    
    var c = 3;
    console.log(c);
}

console.log(c); // ReferenceError: c is not defined
b(); // 1 3

V tomto kódu není možné přistupovat k proměnné c mimo scope funkce b – ta tedy uzavírá rozsah platnosti proměnné c.

Ve funkci b je ale možné přistupovat k proměnné a (globální scope) i proměnné c (scope funkce). Proto zavolání funkce b vypíše 1 i 3.

Deklarace pomocí let se v tomto případě chová stejně.

Function scope / block scope

Zatímco var je tzv. function scope, deklarace let tzv. block scope. Co to znamená?

var a = 1;
if (a === 1) {
    var a = 2;
    console.log(a); // 2
}
console.log(a); // 2

V tomto kódu se v podmínce změní proměnná a na hodnotu 2. Co v případě let?

let a = 1;
if (a === 1) {
    let a = 2;
    console.log(a); // 2
}
console.log(a); // 1

Díky let příklad vypíše mimo podmínku původní 1. Proč?

Složené {závorky} vytvořily blokové scope, čímž se ochránila původní proměnná a. Díky let mohou vedle sebe existovat proměnné stejného názvu, aniž by se ovlivňovaly.

Toto chování u let platí i pro ostatní bloky, nemusí jít o podmínku:

let a = 1;
{
    let a = 2;
    console.log(a); // 2
}
console.log(a); // 1

Na druhou stranu v zanořeném scope je dostupná nadřazená proměnná:

let a = 1;
{
    console.log(a); // 1
}
console.log(a); // 1

Pokud není v bloku definována proměnná stejného názvu. Následující kód tak skončí chybou kvůli přístupu k proměnné před její deklarací:

let a = 1;
{
    console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
    let a;
}
console.log(a);

Cykly

Hodně užitečné je let v cyklech:

for (var i = 0; i < 5; i++) {
    console.log(i); // 0 1 2 3 4
}
console.log(i); // 5

V případě použití var tato proměnná „uteče“ mimo cyklus. Bude dostupná i mimo něj.

let je situace jiná:

for (let i = 0; i < 5; i++) {
    console.log(i); // 0 1 2 3 4
}
console.log(i); // ReferenceError: i is not defined

Na první pohled se může zdát, že je to jedno. Minimalizuje se tím ale riziko, že se nějaká proměnná přepíše někde, kde nemá.

Hodně užitečné to je potom pro případy, kdy se iterátor z cyklu (proměnná i) používá v nějaké asynchronní metodě jako je třeba setTimeout.

for (let i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(i) // 0 1 2 3 4
    },
    100)
}

Co by se stalo s var? Vypsalo by to pětkrát pětku – živá ukázka.

Proč?

Při spuštění tohoto kódu totiž nejdřív proběhne cyklus, čímž vytvoří globální proměnnou s hodnotou 5, potom se teprve provede akce v setTimeout, takže logicky vypíše pokaždé 5.

Bez let je to řešitelné obalením do anonymní funkce, co se rovnou sama zavolá. Tím se kolem vytvoří nový (function) scope, podobně jako při použití let (tam se vytvoří block scope):

for (var i = 0; i < 5; i++) {
    (function(i) {
        setTimeout(function() {
            console.log(i)
        },
        100)
    })(i)
}

Podpora v prohlížečích

Používání let je docela dobře podporované. Jen v IE 11 není podpora úplně plná.

Ideální řešení je ale používat novější JS syntaxi a automaticky ji nechat zkompilovat třeba nástrojem Babel pro starší prohlížeče.

Závěr

Pokud to jde, osvědčilo se mi používat zásadně let a používání var mít zakázané v JS lintu.

Omezenější oblast platnosti proměnných a nemožnost si je omylem přepisovat bývá výhodnější chování, než je používání var.

Odkazy jinam

Komentáře

Odebírat
Upozornit na
guest
2 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
Zobrazit všechny komentáře
Ondřej Žára

Myslím, že správně se scope překládá jako obor platnosti.

Martin Hassman

Díky, to mi uteklo. Našel jsem rozsah platnosti, navíc to autor už dále používá, problém je jen v tom první výskytu, opravím.

Přístupnost není jen o splnění norem: nový pohled na inkluzivní design

Přístupnost a inkluze možná nepatří mezi nejžhavější témata digitálního světa – dokud o nich nezačne mluvit Vitaly Friedman. Na WebExpo 2024 předvedl, že inkluzivní design není jen o splněných checkboxech, ale hlavně o lidech. S energií sobě vlastní obrátil zažité přístupy naruby a ukázal, že skutečně přístupný web je nejen možný, ale i nezbytný.

Efektivnější vývoj UI nebo API: Co si odnést z WebExpo 2025?

Různé
Komentáře: 0
Jak snadno implementovat moderní uživatelské rozhraní? Které funkce brzdí rychlost vašeho webu? A kdy raději sami přibrzdit, abychom využitím AI nepřekročili etické principy? Debatu aktuálních dev témat rozdmýchá sedmnáctý ročník technologické konference WebExpo, která proběhne v Praze od 28. do 30. května. Který talk či workshop si rozhodně nenechat ujít? Toto je náš redakční výběr z vývojářských hroznů.

Zapřáhněte AI jako nikdy předtím. Květnová konference WebExpo přivítá hvězdy technologického světa

Od 28. do 30. května 2025 promění pražský Palác Lucerna na tři dny technologická konference WebExpo. Na programu je více než 80 přednášek a workshopů od expertů z celého světa. WebExpo tradičně propojuje vývojáře, designéry, marketéry i byznysové lídry a nabízí praktické dovednosti, strategické myšlení a přináší nejnovější trendy nejen v oblasti AI.