A JavaScript Call Stack - mi ez és miért szükséges

A JavaScript motor (amely egy olyan tárhelykörnyezetben található, mint a böngésző) egyszálú tolmács, amely kupacból és egyetlen hívásveremből áll. A böngésző olyan webes API-kat nyújt, mint a DOM, AJAX és az Időzítők.

Ez a cikk elmagyarázza, hogy mi a hívásverem, és miért van rá szükség. A hívásverem megértése tisztázza, hogyan működik a „függvényhierarchia és a végrehajtási sorrend” a JavaScript motorban.

A hívásköteget elsősorban függvényhívásra (hívásra) használják. Mivel a hívásverem egyetlen, a funkció (k) végrehajtása egyenként történik, fentről lefelé. Ez azt jelenti, hogy a hívásverem szinkron.

A hívásverem megértése létfontosságú az aszinkron programozás szempontjából (amelyet egy későbbi cikkben fogunk megvizsgálni).

Az aszinkron JavaScript-ben van egy visszahívási funkció, egy eseményhurok és egy feladatsor. A visszahívási funkcióra a hívásverem a végrehajtás során hat, miután a visszahívás funkciót az eseményhurok a verembe tolta.

Mielőtt azonban a fegyverhez ugranánk, próbáljuk meg először megválaszolni a kérdést - Mi a hívásverem?

A legalapvetőbb szinten a hívásverem olyan adatstruktúra, amely a Last In, First Out (LIFO) elvet használja a függvényhívás (hívás) ideiglenes tárolására és kezelésére.

Bontjuk le a definíciónkat:

LIFO: Amikor azt mondjuk, hogy a hívásverem a Last In, First Out adatstruktúra elvével működik, ez azt jelenti, hogy az utolsó függvény, amely a verembe kerül, elsőként jelenik meg, amikor a függvény visszatér.

Vessen egy pillantást egy kódmintára a LIFO bemutatásához, verem nyomkövetési hibát nyomtatva a konzolra.

function firstFunction(){ throw new Error('Stack Trace Error'); } function secondFunction(){ firstFunction(); } function thirdFunction(){ secondFunction(); } thirdFunction();

A kód futtatásakor hibát kapunk. Egy köteg van kinyomtatva, amely megmutatja, hogy a függvények hogyan kerülnek egymásra. Vessen egy pillantást a diagramra.

Észre fogja venni, hogy a megállapodás a funkciók, mint egy köteg kezdődik firstFunction()(amely az utolsó funkció, amely bekerült a verem, és kiugrott, hogy dobja a hiba), majd a secondFunction(), majd a thirdFunction()(ami az első funkció amely a kód végrehajtásakor belekerül a verembe).

Ideiglenes tárolás : Ha egy függvényt meghívnak (meghívják), akkor a függvényt, annak paramétereit és változóit a hívásverembe tolják, hogy veremkeretet alkossanak. Ez a veremkeret memóriahely a veremben. A memória törlődik, amikor a függvény visszatér, amikor kiugrik a veremből.

Funkcióhívás (hívás) kezelése : A hívásverem nyilvántartást vezet az egyes veremkeretek helyzetéről. Tudja a következő végrehajtandó funkciót (és a végrehajtás után eltávolítja). Ez teszi a JavaScript futtatását szinkronossá.

Gondoljon arra, hogy sorban áll, egy élelmiszerbolt pénztárában. Csak akkor vehet részt, ha az előtted lévő személyt ellátták. Ez szinkron.

Ezt értjük „a függvény meghívásának kezelése” alatt.

Hogyan kezeli a hívásverem a hívásokat?

Erre a kérdésre egy olyan függvény mintakódjának megvizsgálásával válaszolunk, amely másik függvényt hív meg. Itt van a példa kód:

function firstFunction(){ console.log("Hello from firstFunction"); } function secondFunction(){ firstFunction(); console.log("The end from secondFunction"); } secondFunction();

A kód futtatásakor ez történik:

1. A secondFunction()végrehajtás után egy üres veremkeret jön létre. Ez a program fő (névtelen) belépési pontja.

2. secondFunction()majd hív, firstFunction()amelyet a verembe tolnak.

3. firstFunction()visszatér és kinyomtatja a „Hello from firstFunction” szót a konzolra.

4. firstFunction()kiugrik a veremből.

5. Ezután lépjen a végrehajtási parancsra secondFunction().

6. secondFunction()visszatér és kinyomtatja a konzolra az „End from secondFunction” végét.

7. secondFunction()megjelenik a veremből, és ezzel törli a memóriát.

Mi okozza a verem túlcsordulását?

Verem túlcsordulás akkor fordul elő, ha rekurzív függvény (egy önmagát hívó függvény) van kilépési pont nélkül. A böngésző (tárhelykörnyezet) rendelkezik egy maximális veremhívással, amelyet képes elhelyezni, mielőtt veremhibát dobna.

Íme egy példa:

function callMyself(){ callMyself(); } callMyself();

Az callMyself()addig fut, amíg a böngésző dob egy „lehívás legnagyobb mérete meghaladta.” És ez egy halom túlcsordulás.

összefoglalva

A legfontosabb elvételek a hívásveremből:

1. Egyszálú. Ez azt jelenti, hogy egyszerre csak egyet tehet.

2. A kód végrehajtása szinkron.

3. A függvényhívás létrehoz egy veremkeretet, amely ideiglenes memóriát foglal el.

4. LIFO - Last In, First Out adatstruktúraként működik.

A call stack cikk segítségével megalapoztuk egy sorozatot, amelyet Asynchronous JavaScript-en fogunk megvizsgálni (amelyet egy másik cikkben fogunk megvizsgálni).

Az összes kódminta megtalálható ebben a GitHub repóban.

Köszönöm, hogy elolvasta. Ha ez a cikk hasznos volt, kérem, adjon néhány tapsot? hogy mások is megtalálják. Szeretném elolvasni az észrevételeit is.