Lexikální scope

AndreaAndrea

V programu máme jmenné prostory proměnných a funkcí. Řešíme nejen jak identifikátory vhodně pojmenovat, ale také kam je umístit. Pozice proměnné je důležitá pro určení, kdy a kde může být proměnná přístupná. Vhodné jméno zase potřebujeme pro to, abysme se nedostali do konfliktu se stejně pojmenovanými proměnnými.

Když kód běží v runtime, pro každý vykonávaný blok kódu (jako je funkční tělo, blok kódu uvnitř {...} atd.) je vytvořen nový LexicalEnvironment. Toto prostředí obsahuje informace o lokálních proměnných, deklaracích a odkaz na vnější LexicalEnvironment, ve kterém byl daný blok vytvořen.

Mnoho programátorů netuší, že vymezení a struktura těchto jmenných prostorů se definuje již během kompilace a nikoliv při běhu programu.

Na pojem lexikální scope dříve či později v JS narazíte a referuje se ním na vlastnost programovacího jazyka. Říká se mu také "statický scope", protože se vytváří na základě struktury kódu během kompilace a nemění se v průběhu běhu programu.

Slovo lexikální přesněji odkazuje na lexer (lexikální analýzu), což je první fáze procesu parsování v kompilaci kódu. Během lexikální analýzy se analyzují deklarace proměnných a funkcí, jejich použití. Rozsahy, které jsou takto definovány, pak určují, kde jsou proměnné viditelné a kde mohou být použity v kódu.

"Lexical Environment" je v podstatě interní objekt, který uchovává přiřazení identifikátorů k jejich funkcím a proměnným. Každá proměnná, funkce a blok kódu má své vlastní lexikální prostředí.

Výhody

Lexikální scope se používá také ve většině programovacích jazycích. Jeho hlavní výhody jsou

  • Předvídatelnost. Prostředí závisí na umístění proměnných a funkcí v kódu během psaní, což znamená, že je vždy pevné a nemění se. To umožňuje programátorům snadno předvídat, kde budou proměnné viditelné a kde budou moci být použity.
  • Optimalizace. Jelikož scope je statický, umožňuje to kompilátorům a interpretrům provést řadu optimalizací. Například mohou být informace o scopu proměnné využity k tomu, aby se určité výpočty a vyhledávání proměnných provedly ještě před spuštěním kódu, což zlepšuje výkon běhu programu.
  • Čitelnost a udržitelnost. Díky lexikálnímu scopingu je snazší pochopit a sledovat, jak a kde jsou proměnné v kódu používány. To zlepšuje čitelnost kódu a usnadňuje jeho údržbu.
  • Zachování kontextu. Lexikální scope také umožňuje vytvářet uzávěry (closures), což jsou funkce, které si "pamatují" svůj původní scope a mají k němu přístup, i když jsou volány mimo něj. To je klíčové pro vytváření modulů a privátních proměnných v JavaScriptu.

Oproti tomu třeba bash, má dynamický scope.

Příklad

Jednoduše řečeno, uvnitř jakékoli funkce máte přístup k proměnným definovaným v této funkci a také k proměnným definovaným v jakémkoli obklopujícím rozsahu (scope).

Podívejme se na příklad v JavaScriptu:

var x = 10; // Globální scope

function outer() {
    var y = 20; // Lokální scope outer funkce

    function inner() {
        var z = 30; // Lokální scope inner funkce

        console.log(x + y + z); // 60
    }

    inner();
}

outer();

V tomto příkladě máme tři proměnné x, y a z definované v různých jmenných proměnných:

  • y je definovaná uvnitř funkce outer
  • x je definovaná na globální úrovni
  • z je definovaná uvnitř funkce inner

Funkce inner má přístup k proměnným ve svém vlastním scopu (z), v obklopujícím scopu (y v funkci outer) a v globálním scopu (x). To je to, co myslíme tím, že "scopy jsou vnořené do sebe".

Co byste si měli odnést

Lexikální scope je také "statický", protože se určuje na základě struktury kódu během kompilace. Tím pádem je scope předvídatelný a není ovlivněný nijak tím, co se děje při běhu programu, protože vše se rozhodlo během kompilace.