Blokový scope a proměnné let a const

AndreaAndrea

Klíčové slova let a const byla přidáno do jazyka ve verzi ECMAScript 2015. V úplně prvotních verzích JavaScriptu šlo proměnnou deklarovat pouze pomocí var.

Dnes už jsou ve všech moderních prohlížečích let a const plně podporovány. A to znamená jediné a to, že je čas rozloučit se s používáním var! Proč se chceme zbavovat něčeho co funguje? Protože používáním blokových rozsahů, můžeme předejít chybám, které nejsou na první pohled patrné.

Blokový rozsah platnosti

K pochopení této problematiky je třeba vědět něco málo o tom jak funguje proměnné prostředí (scope, viditelnost proměnné), pokud nevíte, doporučuji nejprve přečíst tento článek.

V Javascriptu je rozdíl mezi oblastí funkce (function scoping) a bloku (block scoping). Bloková oblast je menší a je vymezena složenými závorkami .

Bloková definice funkce

{
  function foo () { return 1 }
  foo() === 1
  {
    function foo () { return 2 }
    foo() === 2
  }
  foo() === 1
}

Blokové proměnné a funkce jsou dostupné pouze v blokové oblasti, ve které byly deklarováné a nejsou dostupné mimo ni.

Omezení globální proměnné

Obě nová klíčová slova const a let nám dovolují definovat blokovou proměnnou. Naproti tomu proměnná deklarované pomocí var je dostupná v celé funkci nebo dokonce můžou být přístupné globálně.

Když tedy například a deklarujete na globální úrovni pomocí var je proměnná také v prohlížeči přidána do globálního objektu.

var a = 1;

Oproti tomu let nebo const se nestanou součástí globálního objektu i když jsou umístěny stejně.

let b = 2;
const c = 3;

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

V mnoha jazycích jsou konstanty užívany často v globálním scope a jsou používány pro uchování matematické nebo konfigurační hodnoty aplikace. Nicméně const je v tomto smyslu jiný, protože nelze použít globálně.

Dříve se pro takové zapouzřední proměnných používala technika IIFE.

let

Deklarace let se používá pro proměnné, která může být později změněna, tedy přiřazena ji jiná hodnota. Například:

let y = 30;
console.log(y);  // vypíše 30
y = 40;
console.log(y);  // vypíše 40

V tomto se chování neliší od proměnné deklarované pomocí var. Liší se však ve viditelností, protože proměnné let jsou dostupné pouze v bloku.

Hoisting

Hoisting je proces, při kterém se deklarace proměnných a funkcí přesouvají na vrchol souboru nebo bloku kódu. To znamená, že můžete použít proměnnou nebo volat funkci dříve, než ji deklarujete.

Deklarace proměnných s klíčovým slovem var hoistované. Například:

console.log(x);  // vypíše undefined
var x = 10;

Deklarace proměnných s klíčovými slovy let a const nejsou hoistované. To znamená, že se nedají použít dříve, než jsou deklarovány. Pokud se pokusíte použít nezavedenou proměnnou, vyvolá se chyba ReferenceError. Například:

console.log(y);  // vyvolá chybu ReferenceError
let y = 10;

Ve výše uvedeném příkladu se deklarace proměnné y s klíčovým slovem let nedá přesunout na vrchol souboru a pokus o použití proměnné y dříve než její deklarace vyvolá chybu ReferenceError.

Ostatní situace

Existují i další syntaktické formy, které deklarují proměnné v různých situacích. Například:

function hello(myName) {
    console.log(`Hello, ${ myName }.`);
}

Identifikátor hello je vytvořen ve vnějším scope a je také automaticky nastaven tak, aby odkazoval na funkci. Ale pojmenovaný argument myName je vytvořen pouze uvnitř funkce, a je tedy přístupný pouze uvnitř scope této funkce. hello a myName se obecně chovají jako deklarované var.

Další syntaxí, která deklaruje proměnnou, je klauzule catch:

try {
    someError();
}
catch (err) {
    console.log(err);
}

Err je blokově omezená proměnná, která existuje pouze uvnitř klauzule catch, jako by byla deklarována pomocí let.

Podpora

V minulosti se využívala k podpoře let a const transpilace, když aplikace potřebovala běžet v prostředí JS podporujícím před ES6. Nyní je plně podporován ve všech moderních prohlížečích.