JavaScript bajo el capó: bucle de eventos
Dominemos JavaScript explorando su funcionamiento desde cero

¿Alguna vez se ha enfrentado a errores indefinidos o ha tenido problemas para identificar el alcance de una variable?
Realmente lleva mucho tiempo depurar cualquier error sin saber cómo funciona el código.
En este blog, demostraré cómo funcionan realmente los conceptos avanzados event loop
con respecto a execution context
, call stack
y .callback queue
Un descargo de responsabilidad: los conceptos son increíblemente intensivos en conocimiento y están interconectados, ¡así que ni siquiera parpadees!
Motor JavaScript
El motor V8 de Google es una ilustración bien conocida de un motor JavaScript. Por ejemplo, Chrome y Node.js emplean el motor V8. Básicamente, el motor V8 consta de dos partes:
- Pila de llamadas: todo el código se ejecuta dentro de ella. Funciona como la estructura de datos Stack, es decir, siguiendo el concepto LIFO (Last In First Out).
- Montón de memoria: donde se produce la asignación de memoria. A diferencia de la estructura de datos del montón, es solo una memoria.

El contexto de ejecución global o GEC es el contexto de ejecución predeterminado creado por el motor de JavaScript cada vez que se recibe un archivo de script.
Todo el código JavaScript que no está dentro de una función se ejecuta en formato GEC
. Los siguientes pasos se realizan en GEC
:
- Construya un espacio de memoria para almacenar todas las variables y funciones a escala global
- Generar un objeto global.
- Generar la palabra clave
this

Dependiendo de dónde se ejecutará su código, determinará dónde this
se encuentra. Por ejemplo, en Node.js apunta a un objeto global distinto, mientras que en el navegador apunta al window
objeto.

Pila de llamadas (o pila de ejecución de funciones)
JavaScript es single-threaded
, como ya has escuchado. Pero, ¿qué significa realmente?
Significa que un motor de JavaScript contiene solo uno call stack
o function execution stack
.
- Como sabemos, cada vez que el compilador explora su código por primera vez, el compilador le pide al motor JS que cree un
Global Execution Context
oGEC
y que lo coloque en el archivoCall Stack
. - Todo su código se ejecuta uno por uno en el
Global Execution Context
y asigna memoria para la definición de funciones o la declaración de variables y lo almacena allí. - Pero cuando se encuentra cualquier llamada de función, se crea un
Functional Execution Context
oFEC
para ejecutar el código de la función y luego se agrega a la parte superior del archivocall stack
. - El intérprete elimina una función de
call stack
cada vez que la función termina. Una función termina, cuando alcanza el final de su alcance o una declaración de retorno. - Finalmente, la ejecución de todo su código
GEC
se elimina del archivoCall Stack
.
No te preocupes, vamos a demostrarlo con un ejemplo.
function f1{
console.log('f1');
}
f1();
console.log('end');

Paso 2: — En nuestro ejemplo, se ejecutará la primera línea, que es f1
. Se asignará una memoria para f1
su definición y se almacenará.

Paso 3: — En la segunda línea, se llama a una función. Para la invocación de esta función, se creará un Function Execution Context
o y se almacenará encima del .FEC
Call Stack

Paso 4: — Ahora, todo f1()
se ejecutará línea por línea y, una vez finalizada la ejecución, se eliminará del archivo Call Stack
.

Paso 5: — Luego, console.log('end')
se ejecutará la última línea y se imprimirá 'fin' en la consola. Finalmente, al ejecutar todo su código, Global Execution Context
se eliminará del archivo Call Stack
.

¿Cómo gestiona JS las tareas asincrónicas?
JavaScript, como todos somos conocidos, es un lenguaje síncrono de un solo subproceso (una tarea a la vez), y el único subproceso que se call stack
ejecuta de inmediato, lo que sea que esté dentro de él.
Pero, ¿y si necesitamos ejecutar algo después de 5 segundos? ¿Podemos poner eso dentro del call stack
?
No, no podemos. Porque call stack
no tiene ningún temporizador. Pero, ¿cómo podemos hacer eso?
Aquí es donde entra en juego el tiempo de ejecución de JavaScript .

Puede ser desconsolado si te lo digo ahora : no es parte de setTimeout()
JavaScript, aunque los eventos DOM son partes de las API web que brindan acceso al motor JavaScript para usar todas sus propiedades en Global Execution Context (GEC) a través de el objeto mundial . Estas API web se denominan asíncronas .console.log()
window
¿Qué es la cola de devolución de llamada?
Una cola de tareas denominada "cola de devolución de llamadas" o "cola de tareas" es aquella que se ejecuta después de que se hayan completado las tareas actuales de la pila de llamadas. Las tareas que están registradas en la API web pasan de la API web a la cola de devolución de llamada.
La cola de devolución de llamada funciona como una estructura de datos de cola, lo que significa que las tareas se manejan en orden FIFO (primero en entrar, primero en salir), a diferencia de una pila de llamadas, lo que significa que las tareas se manejan en el orden en que se agregaron a la cola.

¿Qué es el bucle de eventos?
Un bucle de eventos de JavaScript agrega una tarea de la cola de devolución de llamada a la pila de llamadas en orden FIFO tan pronto como la pila de llamadas esté vacía.
El bucle de eventos se bloquea si la pila de llamadas está ejecutando algún código y no agregará llamadas adicionales desde la cola hasta que la pila esté vacía una vez más. Esto se debe a que el código JavaScript se ejecuta de manera continua.
Entendamos los conceptos anteriores con un ejemplo.
- Al principio,
Global Execution Context
se crea para nuestro código dentro de nuestrocall stack
yGEC
ejecuta nuestro código línea por línea. GEC
ejecuta la primera línea e imprime 'Inicio' en nuestra consola.- Al ejecutar la segunda línea,
setTimeout()
se llamará a la API web y luegosetTimeout()
dará acceso a la función de temporizador. Entonces podrá establecer5000ms
un tiempo de retraso. - Cuando pase la
callBack()
función a través desetTimeout()
,callBack()
se registrará como una devolución de llamada a través de la API web web. - Y luego
GEC
ejecuta la primera línea e imprime 'Fin' en la consola. - Cuando se ejecute todo el código,
GEC
se eliminará de nuestro archivocall stack
. - Después
5000 millisecond
, lacallBack()
función que está registrada enweb API
, se mueve dentro decall Back Queue
. Event loop
pone lacallBack()
función en elcall Stack
cuando se hace todo es trabajo. Y finalmente, lacallBack()
función se ejecuta e imprime 'Call Back' en la consola.








function f1() {
console.log('f1');
}
function f2() {
console.log('f2');
}
function main() {
console.log('main');
setTimeout(f1, 0);
f2();
}
main();
Si está pensando que "f1" se imprimirá antes que "f2", entonces está equivocado. Será -
main
f2
f1
El mecanismo discutido de JavaScript es adecuado para cualquier función de devolución de llamada o solicitud de API.
Observemos paso a paso cómo funciona el segundo ejemplo dentro del entorno de ejecución.

- Al principio
GEC
se creará dentro delcall stack
y luego se ejecutará el código línea por línea enGEC
. Almacena todas las definiciones de funciones en el montón de memoria . - Cuando
main()
se llama a,Function Execution Context (FEC)
se crea a y luego entra en la pila de llamadas. Después de eso, todo el código de lamain()
función se ejecutará línea por línea. - Tiene un registro de consola para imprimir la palabra principal. Entonces
console.log('main')
se ejecuta y sale de la pila. - La
setTimeout()
API del navegador tiene lugar. La función de devolución de llamada lo coloca en la cola de devolución de llamada. Pero en la pila, la ejecución se produce como de costumbre, por lo quef2()
entra en la pila. El registro de la consola def2()
ejecuciones. Ambos salen de la pila. - Y luego el
main()
también sale de la pila. - El bucle de eventos reconoce que la pila de llamadas está vacía y que hay una función de devolución de llamada en la cola. Por lo tanto, la función de devolución de llamada
f1()
se pondrá en la pila por elevent loop
. Comienza la ejecución. El registro de la consola se ejecuta yf1()
también sale de la pila. Y finalmente, no hay nada más en la pila y en la cola para ejecutar más.
Es mi práctica y nota. Si lo encontró útil, muestre su apoyo haciendo clic en el ícono de aplausos a continuación. Puedes seguirme en medio .