Jak se spouští JavaScript

AndreaAndrea

V době uvedení jazyka Javascriptu byla jedna z lákavých vlastností, že je interpretovaný. To znamená, že kód se před použitím netransformuje do strojového kódu, či spustitelné binarky, ale spouští se většinou webovém prohlížeči. Tak jak se právě stalo, při načtení této stránky, kterou čtete (ano, tato stránka je napsaná v JavaScriptu).

Interpretem bude engine JavaScriptu zabudovaný v prohlížeči. To však není jediný způsob, jak kód JavaScriptu spustit. Možná jste již slyšeli o node.js. Je to také interpre a není to prohlížeč, ale spíš server.

Parsování

Symboly, slova a fráze, které píšeme v textovém editoru, nejsou ve skutečnosti ve formě, které by počítač rozuměl. K nějakému procesu překladu zdrojového kódu z principu musí stále docházet. Náš program se musí převést z textového podoby zdrojového formátu do nějakého reprezentace, kterou umí počítač vykonat a spustit.

Logicky existuje nějaký krok zpracování, který musí proběhnout předtím, než dojde ke spuštění scriptu.

Pokud jste někdy nějaký kód napsali, pak jste si všimli, že stačí tu a tam vynechat čárku, tečku nebo napsat o závorku víč nebo míň a když se pak se pokusíte program spustit okamžitě se ohlásí syntaktická chyba. To je díky parsování. V JS chyba se objeví okamžitě a dříve, než se řádky kde je syntaktická chyba provedou.

Existují i interpretované jazyky, které se neparsují před spuštěním. Například Bash skript, ve kterém když napíšete špatně naformulovaný příkaz na řádku 3, budou předešlé řádky 1, 2 vykonány. Řádek 3 s chybou selže a může se tím pádem něco pokazit, když jste počítali, že projde celá sekvence.

Součástí parsování je proces lexikace a tokenizace. Parsování, které ze serie tokenů vytvoří tzv. abstraktní syntaktický strom.

Většina moderních překladačů jazyka JavaScript používá techniku Just In Time Compilation (JIT Compilation). Tato technika spočívá v kompilaci fragmentů kódu během provádění programu (více než jedna instrukce) a umožňuje zvýšit jeho výkon. Z pohledu uživatele je však taková změna prakticky nepostřehnutelná - stále to vypadá, jako by zdrojový kód vykonával pouze interpret, instrukci po instrukci.

Kompilace?

Pro spuštění JS kódu potřebujeme také vytvořit lexikální scope, kterým se pak řídí běžící program. Tento přístup má několik výhod. Jednou z nich je, že kompilátor může předem provést optimalizace a detekovat chyby. A také díky lexikálnímu rozsahu je snazší analyzovat a provádět kód, protože proměnné prostředí proměnných jsou jasně definována, což vede k rychlejšímu a efektivnějšímu provádění kódu.

I když se děje v mnoha krocích to stejné, co u tradičních kompilovaných jazyků, jako je například C nebo C++. Hlavním rozdíle je, že se nejprve kompilují do strojového kódu, do spustitelného souboru a ten se pak distribuuje a aplikace se spouštějí z něj. JavaScriptový kód je interpretován a spouštěn JavaScriptovým enginem a uživatel si může zároveň přečíst jaký kód na počítači spouští.

Spouštění programu

Co se interně děje, když JavaScriptový engine spouští kód? Proces spouštění kódu má dvě části, které tvoří „prostředí“, ve kterém se kod vykonává tzv. „execution context“ a paměť.

Vlákno

První částí je vlákno, které je vytvořené programem, které se snaží interpretovat jazyk. JavaScript je synchronní (jedno-vláknový), tedy interpretuje se řádek po řádku, od shora dolů. Nikdy, nikdy nepřejde na další řádek, dokud nedokončí úlohu na aktuálním řádku.

Tedy přečte první řádek a vykoná cokoliv co přikazuje. Po té, vezměte řádek dva a udělá to co říká a tak dále.

Při deklaraci proměnné, ukládáme její hodnotu a název do paměti, u funkce (pokud ji zrovna nevoláme), ukládáme název funkce s tělem funkce do paměti.

V JS kódu máme primárně funkce, ale nyní máme také bloky. Při volání funkce, vytváříme nové proměnné prostředí.

Paměť

Paměť je místo kam počítač ukládá data. V případě interpreteru mluvíme spíš o proměnném prostředí. Jde o vyhrazený prostor pro program v hlavní paměti, kam tento program může ukládat data. Vlákno postupně ukládá do zásobníku paměti deklarovné proměnné, těla funkcí a pak výsledek po zavolání funkce.

Kontext

Kontext je prostor ve kterém něco děláme, tedy v našem případě v něm provádíme náš kód. Když klient interpretuje náš kód, první věc, kterou udělá, je vytvoření globálního prostředí. Kdykoli však chceme spustit další kód, například kód uvnitř funkce, vytvoříme malý kontext lokální.

Lokální kontext

V lokálním kontextu nejprve ukládáme parametry funkce a lokální proměnné.