JavaScript Call Call Stack - hvad det er, og hvorfor det er nødvendigt

JavaScript-motoren (som findes i et hostingmiljø som browseren) er en enkelt-trådtolk, der består af en bunke og en enkelt opkaldsstak. Browseren leverer web-API'er som DOM, AJAX og Timers.

Denne artikel har til formål at forklare, hvad opkaldstakken er, og hvorfor det er nødvendigt. En forståelse af opkaldstakken vil give klarhed over, hvordan “funktionshierarki og udførelsesordre” fungerer i JavaScript-motoren.

Opkaldsstakken bruges primært til funktionsopkald (opkald). Da opkaldsstakken er enkelt, udføres funktion (er) udførelse en ad gangen fra top til bund. Det betyder, at opkaldstakken er synkron.

Forståelsen af ​​opkaldsstakken er afgørende for asynkron programmering (som vi vil se på i en senere artikel).

I Asynchronous JavaScript har vi en tilbagekaldsfunktion, en hændelsessløjfe og en opgavekø. Tilbagekaldsfunktionen påvirkes af opkaldstakken under udførelse, efter at tilbagekaldsfunktionen er skubbet til stakken af ​​begivenhedssløjfen.

Men inden vi springer pistolen, lad os først forsøge at besvare spørgsmålet - Hvad er opkaldsstakken?

På det mest basale niveau er en opkaldsstak en datastruktur, der bruger LIFO-princippet (Last In, First Out) til midlertidigt at gemme og administrere funktionsopkald (call).

Lad os nedbryde vores definition:

LIFO: Når vi siger, at opkaldsstakken fungerer efter datastrukturprincippet Last In, First Out, betyder det, at den sidste funktion, der bliver skubbet ind i stakken, er den første, der popes ud, når funktionen vender tilbage.

Lad os se på en kodeeksempel for at demonstrere LIFO ved at udskrive en staksporingsfejl til konsollen.

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

Når koden køres, får vi en fejl. Der udskrives en stak, der viser, hvordan funktionerne er stablet oven på hinanden. Se på diagrammet.

Du vil bemærke, at arrangementet af funktionerne som en stak begynder med den firstFunction()(som er den sidste funktion, der kom ind i stakken, og poppes ud for at kaste fejlen), efterfulgt af secondFunction()og derefter thirdFunction()(som er den første funktion der skubbes ind i stakken, når koden udføres).

Gem midlertidigt : Når en funktion påkaldes (kaldes), skubbes funktionen, dens parametre og variabler ind i opkaldsstakken for at danne en stakramme. Denne stabelramme er en hukommelsesplacering i stakken. Hukommelsen ryddes, når funktionen vender tilbage, når den springer ud af stakken.

Administrer funktionsopkald (opkald) : Opkaldsstakken fører en registrering af positionen for hver stakramme. Den kender den næste funktion, der skal udføres (og fjerner den efter udførelsen). Dette gør kodekørsel i JavaScript synkron.

Tænk på dig selv, der står i en kø i en købmands kontantpoint. Du kan kun overvåges, efter at personen foran dig er blevet deltaget. Det er synkront.

Dette er hvad vi mener med "administrer funktionsopkald".

Hvordan fungerer opkaldsstakens håndteringsopkald?

Vi besvarer dette spørgsmål ved at se på en prøvekode for en funktion, der kalder en anden funktion. Her er eksempelkoden:

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

Dette sker, når koden køres:

1. Når den secondFunction()udføres, oprettes en tom stakramme. Det er programmets vigtigste (anonyme) startpunkt.

2. secondFunction()kalder derefter, firstFunction()som skubbes ind i stakken.

3. firstFunction()vender tilbage og udskriver “Hello from firstFunction” til konsollen.

4. firstFunction()er pop fra stakken.

5. Udførelsesordren flyttes derefter til secondFunction().

6. secondFunction()vender tilbage og udskriver "The end from secondFunction" til konsollen.

7. secondFunction()er pop fra stakken og rydder hukommelsen.

Hvad forårsager et stackoverløb?

Et stakoverløb opstår, når der er en rekursiv funktion (en funktion, der kalder sig selv) uden et udgangspunkt. Browseren (værtsmiljø) har et maksimalt stak-opkald, som det kan rumme, inden der kastes en stakfejl.

Her er et eksempel:

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

Den callMyself()kører, indtil browseren kaster en "Maksimal opkaldsstørrelse overskredet". Og det er et stackoverløb.

Sammenfattende

De vigtigste takeaways fra opkaldstakken er:

1. Det er enkelt gevind. Det betyder, at det kun kan gøre en ting ad gangen.

2. Kodeudførelse er synkron.

3. En funktionsopkald opretter en stakramme, der optager en midlertidig hukommelse.

4. Det fungerer som en LIFO - Last In, First Out datastruktur.

Vi har brugt call stack-artiklen til at lægge grundlaget for en serie, vi vil se på på Asynchronous JavaScript (som vi vil se på i en anden artikel).

Alle kodeeksempler kan findes i denne GitHub repo.

Tak fordi du læste. Hvis denne artikel var nyttig, bedes du give den nogle klapper? så andre kan finde det. Jeg vil også gerne læse dine kommentarer.