Command Palette

Search for a command to run...

Execution Context y Call Stack en JavaScript

Entiende cómo JavaScript ejecuta el código a través del execution context y la call stack, las fases de creación y ejecución, y cómo esto afecta el hoisting y el scope.

Lectura: 12 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • Execution Context: entorno donde se ejecuta código JavaScript
  • Tipos: global, función y eval (desaconsejado)
  • Call Stack: pila que rastrea execution contexts activos
  • Fases: creación (hoisting) y ejecución del código
  • Hoisting: elevación de declaraciones al inicio del contexto
  • LIFO: Last In, First Out - el último en entrar es el primero en salir

¿Qué es el Execution Context?

El Execution Context es el entorno abstracto donde JavaScript evalúa y ejecuta código. Contiene todo lo que JavaScript necesita saber para ejecutar código: variables, funciones, el valor de this, y referencias al scope externo. Cada vez que JavaScript ejecuta código, crea un nuevo execution context.

Puedes pensar en el execution context como el "espacio de trabajo" de JavaScript. Cuando JavaScript ejecuta una función, crea un execution context específico para esa función con sus propias variables, parámetros, y referencias. Este contexto existe solo mientras la función se está ejecutando y es destruido cuando la función termina.

Contexto abstracto

El execution context es un concepto abstracto del motor JavaScript. No es algo que puedas acceder directamente en tu código, pero entender cómo funciona te ayuda a escribir mejor código y debuggear más efectivamente.

Tipos de Execution Context

JavaScript tiene tres tipos principales de execution context: global, de función, y eval. Cada tipo tiene características específicas y se crea en circunstancias diferentes. Entender estos tipos es fundamental para comprender cómo JavaScript organiza y ejecuta código.

tipos-execution-context.js
Loading code...

El ejemplo muestra los diferentes tipos de execution context. El execution context global se crea cuando JavaScript comienza a ejecutar el script. Los execution contexts de función se crean cada vez que se invoca una función. El execution context de eval se crea cuando se usa la función eval(), aunque su uso está fuertemente desaconsejado por razones de seguridad y rendimiento.

  • <strong>Global:</strong> Creado cuando JavaScript comienza a ejecutar código
  • <strong>Función:</strong> Creado cada vez que se invoca una función
  • <strong>Eval:</strong> Creado cuando se usa <code>eval()</code> (desaconsejado)
  • <strong>Único global:</strong> Solo existe un execution context global por script
  • <strong>Múltiples función:</strong> Se crean múltiples contexts de función

Evita eval()

La función eval() crea execution contexts de eval, pero su uso está fuertemente desaconsejado. Es lento, representa un riesgo de seguridad, y dificulta la optimización del código.

La Call Stack

La Call Stack es una estructura de datos LIFO (Last In, First Out) que JavaScript usa para rastrear los execution contexts activos. Cuando se invoca una función, JavaScript añade su execution context al tope de la call stack. Cuando la función termina, JavaScript remueve su context de la call stack.

call-stack.js
Loading code...

El ejemplo muestra cómo la call stack funciona con funciones anidadas. Cuando invocamos uno(), su context se añade a la stack. uno() invoca dos(), cuyo context se añade encima. dos() invoca tres(), cuyo context se añade al tope. Las funciones terminan en orden inverso: tres() primero, luego dos(), y finalmente uno().

  1. <strong>Push:</strong> Cuando se invoca una función, su context se añade a la stack
  2. <strong>Top:</strong> La función activa siempre está en el tope de la stack
  3. <strong>Pop:</strong> Cuando una función termina, su context se remueve de la stack
  4. <strong>LIFO:</strong> Last In, First Out - el último en entrar es el primero en salir
  5. <strong>Stack overflow:</strong> Ocurre cuando la stack excede su tamaño máximo

Stack overflow

El stack overflow ocurre cuando la call stack excede su tamaño máximo, típicamente por recursión infinita o demasiados niveles de anidamiento. El error "Maximum call stack size exceeded" indica este problema.

Creación de Execution Context

Cuando JavaScript crea un execution context, sigue un proceso específico que define las variables, funciones, y el scope del contexto. Este proceso ocurre en dos fases principales: la fase de creación y la fase de ejecución. Entender estas fases es clave para comprender el hoisting y cómo JavaScript inicializa variables.

creacion-execution-context.js
Loading code...

El ejemplo muestra cómo se crea un execution context para la función ejemplo. Durante la fase de creación, JavaScript crea el objeto variable con las declaraciones de var (elevadas a undefined), las declaraciones de función (completamente elevadas), y determina el valor de this. Durante la fase de ejecución, JavaScript ejecuta el código línea por línea, asignando valores a las variables.

El proceso de creación incluye varios pasos importantes: primero se crea el objeto variable y se determina this, luego ocurre el hoisting donde las declaraciones de función se elevan completamente mientras que las variables var se elevan pero se inicializan como undefined. Durante la fase de ejecución se ejecuta el código y se asignan valores a las variables. También se crea la scope chain que referencia al scope externo, permitiendo que las funciones accedan a variables de ámbitos superiores.

Objeto variable

El objeto variable (Variable Object) es parte del execution context que contiene las declaraciones de variables y funciones. Aunque es un concepto interno del motor JavaScript, entenderlo ayuda a comprender el hoisting.

Fases del Execution Context

El execution context tiene dos fases principales: la fase de creación y la fase de ejecución. Cada fase tiene tareas específicas que JavaScript realiza para preparar y ejecutar código. Entender estas fases es fundamental para comprender el hoisting, el scope, y cómo JavaScript inicializa variables.

fases-execution-context.js
Loading code...

El ejemplo muestra las dos fases del execution context. En la fase de creación, JavaScript crea el objeto variable con las declaraciones (elevadas) y determina this. En la fase de ejecución, JavaScript ejecuta el código, asigna valores a las variables, y puede crear nuevos execution contexts si se invocan funciones.

El flujo comienza con la fase de creación donde se crea el objeto variable y se determina this, seguido del hoisting que eleva las declaraciones al inicio del contexto. Luego viene la fase de ejecución donde se ejecuta el código línea por línea, asignando valores a las variables durante esta fase. Si se invocan funciones durante la ejecución, se crean nuevos execution contexts que siguen el mismo proceso de creación y ejecución.

Temporal Dead Zone

Con let y const, las variables existen pero no son accesibles desde el inicio del scope hasta la declaración. Este período es la Temporal Dead Zone (TDZ), y intentar acceder a las variables causa un ReferenceError.

Hoisting y Execution Context

El hoisting es el comportamiento de JavaScript de mover declaraciones al inicio de su execution context durante la fase de creación. Las declaraciones de función se elevan completamente, mientras que las declaraciones de var se elevan pero se inicializan como undefined. Entender el hoisting es esencial para escribir código predecible.

hoisting-execution-context.js
Loading code...

El ejemplo muestra cómo el hoisting funciona en el execution context. Durante la fase de creación, la declaración de miFuncion se eleva completamente, permitiendo invocarla antes de su declaración en el código. La declaración de miVariable se eleva pero se inicializa como undefined, por lo que su valor es undefined hasta la asignación.

El comportamiento del hoisting varía según el tipo de declaración: las declaraciones de funciones se elevan completamente con su implementación, mientras que las variables var se elevan pero se inicializan como undefined. Las variables let y const no se elevan de la misma manera y causan un ReferenceError si se acceden antes de su declaración debido a la Temporal Dead Zone. El hoisting ocurre durante la fase de creación, pero es importante notar que las expresiones de función no se elevan, solo las declaraciones.

Hoisting con let/const

Las variables declaradas con let y const no se elevan como var. Intentar acceder a ellas antes de su declaración causa un ReferenceError debido a la Temporal Dead Zone.

Resumen

Resumen: Execution Context y Call Stack

Conceptos principales:

  • Execution Context: entorno donde se ejecuta código JavaScript
  • Tipos: global, función y eval (desaconsejado)
  • Call Stack: pila LIFO que rastrea contexts activos
  • Fases: creación (hoisting) y ejecución del código
  • Hoisting: elevación de declaraciones al inicio del contexto
  • Objeto variable: contiene declaraciones del contexto

Implicaciones:

  • Las funciones crean nuevos execution contexts
  • La call stack gestiona el orden de ejecución
  • El hoisting ocurre durante la fase de creación
  • Stack overflow ocurre por recursión infinita
  • let/const tienen Temporal Dead Zone
  • this se determina al crear el execution context