Saltearse al contenido

Hoisting

El concepto de Hoisting fue pensado como una manera general de referirse a cómo funcionan los contextos de ejecución en JavaScript (específicamente las fases de creación y ejecución).

Cabe destacar que el hoisting no existía antes de la versión ES6 de JavaScript (2015). Sin embargo, el concepto es útil para entender cómo funcionan las variables y las funciones en JavaScript.

Concepto

El hoisting es el comportamiento por el cual las declaraciones de variables y definiciones funciones son movidas al comienzo de su contexto de ejecución durante la fase de creación.

En otras palabras, las variables y funciones son “elevadas” al comienzo de su contexto de ejecución, es decir, al principio del código.

Para comprender el hoisting, es importante conocer los contextos de ejecución y las fases de creación y ejecución. Por lo tanto, es recomendable leer primero el anexo Contexto de ejecución.

Variables

Como sabemos en JavaScript, podemos declarar variables mediante las palabras reservadas var, let y const. Dependiendo de la palabra reservada que utilicemos, el comportamiento de hoisting será diferente.

Hoisting con var

Cuando el intérprete de JavaScript encuentra una declaración de variable con var, inicializa su valor como undefined.

1
console.log(message); // undefined
2
3
var message = "Hola Mundo";
4
5
console.log(message); // Hola Mundo

Esto se debe a que el intérprete de JavaScript divide la declaración y la asignación de la variable en fases diferentes. Por lo cual, podríamos tener el mismo comportamiento si escribimos redefinieramos el código anterior de la siguiente manera:

1
var message;
2
3
console.log(message); // undefined
4
5
message = "Hola Mundo";
6
7
console.log(message); // Hola Mundo

Veremos que message es elevada al comienzo del contexto de ejecución, pero su valor no es asignado hasta después de la ejecución de la primera sentencia console.log. Por lo tanto, la primera sentencia console.log muestra undefined.

Una variable declarada con var nunca mostrará un error de referencia (ReferenceError) si se intenta acceder a ella antes de su declaración.

Este comportamiento puede ser confuso y propenso a errores, razón por la cual se introdujeron las palabras reservadas let y const en la versión ES6 de JavaScript.

Hoisting con let y const

Las variables declaradas con let y const también son elevadas al comienzo de su contexto de ejecución, pero no son inicializadas. Por lo tanto, si intentamos acceder a una variable declarada con let o const antes de su declaración, obtendremos un error de referencia (ReferenceError).

1
console.log(message); // ReferenceError: Cannot access 'message' before initialization
2
3
let message = "Hola Mundo";
4
5
console.log(message); // Hola Mundo

Es importante tener en cuenta que el intérprete si reconoce que la variable message existe y es inicializada en algún punto del código, pero no permite acceder a ella antes de su declaración.

Esto se debe a la zona muerta temporal (Temporal Dead Zone o TDZ), la cual es el período entre la elevación de una variable y su inicialización. Durante este período, si intentamos acceder a una variable declarada con let o const, obtendremos un error de referencia (ReferenceError).

Funciones

Las declaraciones de funciones también son elevadas, pero no las expresiones de funciones. Es decir, el hoisting de funciones se aplica a las funciones declaradas con la palabra reservada function.

Al elevar una función, se nos permite llamarla antes de su declaración.

1
greet(); // Hola Mundo
2
3
function greet() {
4
console.log("Hola Mundo");
5
}

La razón por la cual las expresiones de funciones no son elevadas es porque son tratadas como cualquier otra variable.

1
greet(); // TypeError: greet is not a function
2
3
var greet = function() {
4
console.log("Hola Mundo");
5
}

Si intentamos invocar una expresión de función declarada con var antes de su declaración, obtendremos un error de tipo (TypeError), ya que la variable greet es inicializada como undefined.

1
greet(); // ReferenceError: Cannot access 'greet' before initialization
2
3
let greet = function() {
4
console.log("Hola Mundo");
5
}

Por otro lado, si intentamos invocar una expresión de función declarada con let o const antes de su declaración, obtendremos un error de referencia (ReferenceError), ya que la variable greet se encuentra en la zona muerta temporal (Temporal Dead Zone o TDZ).

Conclusión

El hoisting es un comportamiento que nos permite acceder a variables y funciones antes de su declaración. Sin embargo, es importante tener en cuenta que las variables declaradas con var son inicializadas como undefined, mientras que las variables declaradas con let y const no son inicializadas y se encuentran en la zona muerta temporal (Temporal Dead Zone o TDZ).

Como recomendación, si trabajamos con un proyecto Greenfield, es decir, un proyecto nuevo sin restricciones de compatibilidad con versiones anteriores de JavaScript, es preferible utilizar let y const.

En cambio, si trabajamos con un proyecto existente con restricciones de compatibilidad con versiones anteriores de JavaScript, es preferible realizar las declaraciones de variables al comienzo de su contexto de ejecución con var.

En cuanto a las funciones, es una preferencia personal como aprovechar el hoisting.

  • Algunos desarrolladores prefieren declarar todas las funciones al final del archivo, para tener una mejor lectura del código.
  • Otros desarrolladores prefieren declarar las funciones en archivos separados, para tener un mejor control de la modularidad.

Bibliografía