Proč místo var používat let a const?

AndreaAndrea

V původních verzích JavaScriptu se proměnná deklarovala pouze pomocí klíčového slova var. To, že se ve verzi ES 2015 zavedly další způsoby deklarování pomocí klíčových slov let a const mělo důvod.

Bez ohledu na to, jestli jste začínající nebo zkušenější programátor, který se s let nebo const zatím nesetkal, je důležité nejdřív pochopit koncept proměnného prostředí.

Hoisting

Proměnná deklarovaná slovem var je skutečně přístupná před její deklarací díky procesu "hoistingu". Pokud se pokusíte přistoupit k takové proměnné, nevyvolá se chyba ReferenceError, jak byste mohli očekávat (např. z chování jiných jazyků), ale vrátí se hodnota undefined.

console.log(myVar); // undefined
var myVar = 21;
console.log(myVar); // 21

Toto chování může být matoucí, což je jeden z důvodů, proč se doporučuje používat let a const v novějších verzích JavaScriptu. Tyto proměnné jsou také vystaveny hoistingu, ale pokud se k nim pokusíte přistoupit před jejich deklarací, vyvolá se chyba ReferenceError, což může být při ladění kódu užitečnější.

Použítí var v blocích (cyklu)

Podíváme na rozdíly v používání mezi var a let v cyklech. Představme si scénář, kdy vytváříte pole funkcí v cyklu a každá funkce by měla vypsat číselnou hodnotu odpovídající její pozici (indexu) v poli.

  1. Vytvoříme pole s názvem funkce.
var funkce = [];

Protože si chceme ušetřit práci s vytvářením mnoha funkcí využijeme cyklu, pomocí kterého je vytvoříme naráz:

for (var i = 0; i < 3; i++) {
	// uložíme si jednotlivé funkce do proměnné
	funkce[i] = function() {
		// každý z nich by měl zaznamenat svou hodnotu.
		console.log("Hodnota: " + i);
	};
}

Vidíte už problém? Pokud ne, můžeme si zkusit tyto funkce spustit, abychom viděli jak si pamatují proměnnou i.

for (var j = 0; j < 3; j++) {
	funkce[j]();
}

Pokud použijete var pro deklaraci indexu cyklu, můžete narazit na neočekávané chování - každá funkce vypíše stejnou hodnotu, a tou je poslední hodnota indexu po doběhnutí cyklu. Příčinou je, že všechny funkce odkazují na tu stejnou proměnnou i a protože jsou volány později, proměnná i bude mít hodnotu 3. Pouhé deklarování i místo jako let by pomohlo předejít problému.

Viditelnost

Klíčové slovo var je viditelné ve funkčním scope, takže proměnná i je sdílena mezi všemi iteracemi cyklu. Naproti tomu let a const způsobí omezení platnosti proměnných na úrovni blokového scope.

V tomto příkladu deklarujeme i pomocí let v cyklu:

for (let i = 0; i < 5; i++) {
  console.log(i);  // vypíše 0, 1, 2, 3, 4
}
console.log(i);  // vyvolá chybu ReferenceError

Pokud se pokusíte přistoupit k proměnné y nebo i zvenčí cyklu, vyvolá se chyba ReferenceError. Rozšíření JS o blokový scope poskytlo programátorům lepší kontrolu nad používáním proměnných v našich programech. To pomáhá zabránit konfliktům se stejnými jmény... Zrovna v cyklech a jednoduchých konstrukcích, totiž často recyklujeme jednopísmenkové proměnné.