JavaScript sotto il cofano: ciclo di eventi
Padroneggiamo JavaScript esplorando il suo funzionamento da zero
Hai mai affrontato errori non definiti o faticato a identificare l'ambito di una variabile?
È davvero dispendioso in termini di tempo eseguire il debug di qualsiasi errore senza sapere come funzionava il codice.
In questo blog, dimostrerò come funzionano effettivamente concetti avanzati come event loop, execution context, call stacke .callback queue
Un disclaimer: i concetti sono incredibilmente intensivi di conoscenza e interconnessi, quindi per favore non battere ciglio!
Motore JavaScript
Il motore V8 di Google è un noto esempio di un motore JavaScript. Ad esempio, Chrome e Node.js utilizzano entrambi il motore V8. Fondamentalmente, il motore V8 è composto da due parti:
- Stack di chiamate: tutto il codice viene eseguito al suo interno. Funziona come la struttura dati Stack, ovvero seguendo il concetto LIFO (Last In First Out).
- Memory Heap: dove si verifica l'allocazione della memoria. A differenza della struttura dati dell'heap, è solo un ricordo.
Il contesto di esecuzione globale o GEC è il contesto di esecuzione predefinito creato dal motore JavaScript ogni volta che viene ricevuto un file di script.
Tutto il codice JavaScript che non si trova all'interno di una funzione viene eseguito in GEC. I seguenti passaggi vengono eseguiti in GEC:
- Costruisci uno spazio di memoria per memorizzare tutte le variabili e le funzioni su scala globale
- Genera un oggetto globale.
- Genera la parola chiave
this
A seconda di dove verrà eseguito il codice determinerà dove thissi trova. Ad esempio, in Node.js punta a un oggetto globale distinto, mentre nel browser punta windowall'oggetto.
Stack di chiamate (o stack di esecuzione delle funzioni)
JavaScript è single-threaded, come hai già sentito. Ma cosa significa in realtà?
Significa che un motore JavaScript contiene solo uno call stacko function execution stack.
- Come sappiamo, ogni volta che il compilatore esplora per la prima volta il tuo codice, al motore JS viene chiesto di creare un
Global Execution ContextoGECdal compilatore e di inserirlo nel fileCall Stack. - L'intero codice viene eseguito uno per uno in
Global Execution Contexte alloca la memoria per la definizione della funzione o la dichiarazione della variabile e la memorizza lì. - Ma quando viene trovata una chiamata di funzione, viene creato un
Functional Execution ContextoFECper eseguire il codice della funzione e quindi viene aggiunto all'inizio del filecall stack. - L'interprete rimuove una funzione da
call stackogni volta che la funzione termina. Una funzione termina — quando raggiunge la fine del suo ambito o un'istruzione return. - Infine, l'esecuzione dell'intero codice
GECviene rimossa dal fileCall Stack.
Non preoccuparti, dimostriamolo con un esempio.
function f1{
console.log('f1');
}
f1();
console.log('end');
Passaggio 2: — Nel nostro esempio, verrà eseguita la prima riga che è f1. Verrà assegnata f1e archiviata una memoria per la sua definizione.
Fase 3: — Nella seconda riga viene richiamata una funzione. Per questa chiamata di funzione, verrà creato un Function Execution Context o FECe verrà memorizzato sopra il file Call Stack.
Passaggio 4: - Ora, l'intero f1()verrà eseguito riga per riga e dopo aver terminato l'esecuzione verrà rimosso dal file Call Stack.
Passaggio 5: — Quindi, l'ultima riga console.log('end')verrà eseguita e stamperà 'end' sulla console. Infine, eseguendo l'intero codice, Global Execution Contextverrà rimosso dal file Call Stack.
In che modo JS gestisce le attività asincrone?
JavaScript, come tutti sappiamo, è un linguaggio sincrono a thread singolo (un'attività alla volta) e il singolo thread che call stackesegue immediatamente qualunque cosa arrivi al suo interno.
Ma cosa succede se dobbiamo eseguire qualcosa dopo 5 secondi? Possiamo indossarlo all'interno del call stack?
No, non possiamo. Perché call stacknon ha nessun timer. Ma come possiamo farlo?
È qui che entra in gioco il runtime JavaScript .
Può essere spezzato il cuore se te lo dico ora setTimeout(): non fa parte di JavaScript, anche se console.log()o gli eventi DOM sono tutte parti delle API Web che danno accesso al motore JavaScript per utilizzare tutte le sue proprietà nel Global Execution Context (GEC) tramite l'oggetto globale window. Queste API Web sono denominate asincrone .
Cos'è la coda di richiamata?
Una coda di attività chiamata "coda di richiamata" o "coda di attività" viene eseguita dopo che le attività correnti dello stack di chiamate sono state completate. Le attività registrate nell'API Web vengono spostate dall'API Web alla coda di richiamata.
La coda di richiamata funziona come una struttura di dati della coda, il che significa che le attività vengono gestite in ordine FIFO (first in, first out), al contrario di uno stack di chiamate, il che significa che le attività vengono gestite nell'ordine in cui sono state aggiunte alla coda.
Cos'è il ciclo di eventi?
Un ciclo di eventi JavaScript aggiunge un'attività dalla coda di richiamata allo stack di chiamate in ordine FIFO non appena lo stack di chiamate è vuoto.
Il ciclo di eventi è bloccato se lo stack di chiamate sta attualmente eseguendo del codice e non aggiungerà ulteriori chiamate dalla coda fino a quando lo stack non sarà nuovamente vuoto. Questo perché il codice JavaScript viene eseguito in modalità run-to-complete.
Comprendiamo i concetti di cui sopra con un esempio.
- All'inizio,
Global Execution Contextviene creato per il nostro codice all'interno di ourcall stackedGECesegue il nostro codice riga per riga. GECesegue la prima riga e stampa 'Start' sulla nostra console.- Eseguendo la seconda riga,
setTimeout()l'API Web verrà chiamata e quindisetTimeout()consentirà l'accesso alla funzione timer. Quindi sarai in grado di impostare5000mscome tempo di ritardo. - Quando si passa la
callBack()funzione tramitesetTimeout(),callBack()verrà registrata come API Web di richiamata su web. - E quindi
GECesegue la prima riga e stampa "End" sulla console. - Quando tutto il codice viene eseguito,
GECverrà rimosso dal nostro filecall stack. - Successivamente
5000 millisecond, lacallBack()funzione registrata inweb API, viene spostata all'interno dicall Back Queue. Event loopmette lacallBack()funzione incall Stackquando ha finito è tutto lavoro. Infine, lacallBack()funzione viene eseguita e stampa "Richiama" nella console.
function f1() {
console.log('f1');
}
function f2() {
console.log('f2');
}
function main() {
console.log('main');
setTimeout(f1, 0);
f2();
}
main();
Se stai pensando che "f1" verrà stampato prima di "f2", allora ti sbagli. Sarà -
main
f2
f1
Il meccanismo discusso di JavaScript è adatto a qualsiasi funzione di callback o richiesta API.
Osserviamo passo dopo passo come funziona il secondo esempio all'interno dell'ambiente di runtime.
- Inizialmente
GECverrà creato all'interno dicall stacke quindi il codice verrà eseguito riga per riga inGEC. Memorizza tutte le definizioni delle funzioni nell'heap della memoria . - Quando
main()viene chiamato,Function Execution Context (FEC)viene creato a e quindi entra nello stack di chiamate. Successivamente tutto il codice dellamain()funzione verrà eseguito riga per riga. - Ha un log della console per stampare la parola main. Quindi
console.log('main')viene eseguito ed esce dallo stack. - L'
setTimeout()API del browser ha luogo. La funzione di richiamata lo inserisce nella coda di richiamata. Ma nello stack, l'esecuzione avviene come al solito, quindif2()entra nello stack. Il log della console dellef2()esecuzioni. Entrambi escono dalla pila. - E poi
main()salta anche fuori dalla pila. - Il ciclo di eventi riconosce che lo stack di chiamate è vuoto e nella coda è presente una funzione di callback. Quindi, la funzione di callback
f1()verrà inserita nello stack dalevent loop. L'esecuzione ha inizio. Il registro della console viene eseguito edf1()esce anche dallo stack. E infine, nient'altro è nello stack e nella coda per essere eseguito ulteriormente.
È la mia pratica e nota. Se lo hai trovato utile, mostra il tuo supporto facendo clic sull'icona di applauso in basso. Puoi seguirmi su medium .

![Che cos'è un elenco collegato, comunque? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































