JavaScript es un lenguaje síncrono (se mueve a la siguiente línea solo cuando se completa la ejecución de la línea actual) y de subproceso único (ejecuta un comando a la vez en un orden específico uno tras otro en serie). Para saber entre bastidores cómo se ejecuta internamente el código JavaScript, debemos conocer algo llamado Contexto de ejecución y su función en la ejecución del código JavaScript.
Contexto de ejecución: todo en JavaScript está envuelto dentro del contexto de ejecución, que es un concepto abstracto (puede tratarse como un contenedor) que contiene toda la información sobre el entorno en el que se ejecuta el código JavaScript actual.
Ahora, un contexto de ejecución tiene dos componentes y el código JavaScript se ejecuta en dos fases.
- Fase de asignación de memoria: en esta fase, todas las funciones y variables del código JavaScript se almacenan como un par clave-valor dentro del componente de memoria del contexto de ejecución. En el caso de una función, JavaScript copió toda la función en el bloque de memoria, pero en el caso de las variables, asigna indefinido como marcador de posición.
- Fase de ejecución de código: en esta fase, el código JavaScript se ejecuta una línea a la vez dentro del componente de código (también conocido como subproceso de ejecución) del contexto de ejecución.
Veamos todo el proceso a través de un ejemplo.
Javascript
var number = 2; function Square (n) { var res = n * n; return res; } var newNumber = Square(3);
En el código JavaScript anterior, hay dos variables llamadas número y nuevoNúmero y una función llamada Cuadrado que devuelve el cuadrado del número. Entonces, cuando ejecutamos este programa, se crea un contexto de ejecución global.
Entonces, en la fase de asignación de memoria, la memoria se asignará para estas variables y funciones como esta.
En la Fase de Ejecución de Código, JavaScript, que es un lenguaje de un solo subproceso, vuelve a ejecutar el código línea por línea y actualiza los valores de función y variables que se almacenan en la Fase de Asignación de Memoria en el Componente de Memoria.
Entonces, en la fase de ejecución del código, cada vez que se llama a una nueva función, se crea un nuevo contexto de ejecución. Entonces, cada vez que se invoca una función en el componente de código, se crea un nuevo contexto de ejecución dentro del contexto de ejecución global anterior.
De nuevo, antes de que se complete la asignación de memoria en el componente de memoria del nuevo contexto de ejecución. Luego, en la Fase de Ejecución de Código del Contexto de Ejecución recién creado, el Contexto de Ejecución global tendrá el siguiente aspecto.
Como podemos ver, los valores se asignan en el componente de memoria después de ejecutar el código línea por línea, es decir, número: 2, res: 4, newNumber: 4.
Después de la declaración de devolución de la función invocada, el valor devuelto se asigna en lugar de indefinido en la asignación de memoria del contexto de ejecución anterior. Después de devolver el valor, el nuevo contexto de ejecución (temporal) se elimina por completo. Cada vez que la ejecución encuentra la declaración de retorno, devuelve el control al contexto de ejecución donde se invocó la función.
Después de ejecutar la primera llamada de función cuando volvemos a llamar a la función, JavaScript crea de nuevo otro contexto temporal donde se repite el mismo procedimiento en consecuencia (ejecución de memoria y ejecución de código). Al final, el contexto de ejecución global se elimina al igual que los contextos de ejecución secundarios. Se eliminará todo el contexto de ejecución para la instancia de esa función.
Pila de llamadas: cuando un programa comienza a ejecutarse, JavaScript empuja todo el programa como contexto global a una pila que se conoce como Pila de llamadas y continúa la ejecución. Cada vez que JavaScript ejecuta un nuevo contexto y simplemente sigue el mismo proceso y lo empuja a la pila. Cuando finaliza el contexto, JavaScript simplemente aparece en la parte superior de la pila en consecuencia.
Cuando JavaScript completa la ejecución de todo el código, el contexto de ejecución global se elimina y sale de la pila de llamadas, lo que hace que la pila de llamadas quede vacía.