javascript-hoisting

Hoisting en JavaScript

En JavaScript, el Hoisting es un comportamiento del motor de JavaScript que afecta la forma en que se interpretan las declaraciones de variables y funciones.

El hoisting hace que las declaraciones de variables y funciones sean “elevadas” al inicio de su contexto de ejecución.

Con “elevar” la declaración queremos decir, que el intérprete sabe que existe una función, aunque la declaremos más adelante en el código.

El hoisting es una característica muy útil, que nos facilita el desarrollo. Sin embargo, también es uno de los conceptos menos entendidos y que generan más confusión.

javascript-hoisting

Así que vamos a verla 👇

Para que sirve el Hoisting

Como decía, el Hoisting consiste en que el intérprete conoce las variables o funciones, antes de su declaración. Es decir, que podemos hacer esto.

saludar(); // Output: "Hola, mundo!"

function saludar() {
    console.log("Hola, mundo!");
}

En este caso,

  • La función saludar se puede llamar antes de su declaración
  • Esto es así porque porque el Hoisting “eleva” la declaración.

Así leído puede parecer un poco raro, pero tiene mucho sentido. El propósito del Hoisting es simplificarnos la vida al escribir el código.

Si no tuviéramos Hoisting, tendríamos que escribir las funciones en el mismo orden en el que las usamos.

function funcion1() {
    console.log("Hola, mundo!");
}

function funcion2() {
	funcion1();
}

Lo cuál puede parecer un problema pequeño. Pero a medida que escribes código, tendrías que estar constantemente cambiando el orden de las funciones (para que estén en el mismo orden en que las usas).

Esto sería un auténtico peñazo 🙅. Así que el intérprete primero se da una vuelta por todo el fichero recopilando las definiciones, para que sea más cómodo para nosotros.

JavaScript no es el único lenguaje que tiene este “problema”. La mayoría de lenguajes modernos, no exigen que se mantenga el orden.

Otros sí lo requieren, como por ejemplo C++. Entonces necesitan otros mecanismos como ficheros .header o fordward declaration, que son incluso menos intuitivas.

Como funciona el Hoisting

Hoisting de funciones

Las funciones en JavaScript son elevadas por completo, tanto la declaración como la implementación se elevan al inicio del contexto de ejecución.

Esto significa que puedes invocarlas antes de su declaración. Veamos un ejemplo:

console.log(sumar(5, 3)); // 8

function sumar(a, b) {
    return a + b;
}

Aquí, la llamada a sumar se realiza antes de la declaración de la función

Hoisting con variables

Las declaraciones de variables utilizando let y const también se elevan. Sin embargo, no están disponibles antes de su declaración real.

Esto se debe a que el interprete las pone en lo que llamamos TDZ (temporal dead zone) hasta que se alcanza su declaración.

console.log(miLetVariable); 
// ReferenceError: Cannot access 'miLetVariable' before initialization

let miLetVariable = 10;

En este caso, el código lanza un ReferenceError porque miLetVariable no está definida antes de su declaración.

Se suele decir que se eleva la definición, pero no la inicialización. Da un poco igual, lo importante es que la TDZ no te va a dejar acceder a ella.

Ejemplo: Variable que contiene una función

Vamos a ver un ejemplo con caso que puede puede generar algo de confusión. ¿Qué pasa si tenemos una variable que contiene una función?

Bueno, que una variable que contiene una función, sigue siendo una variable. Así que va a seguir las reglas que hemos visto de comportamiento de una variable.

Supongamos este caso,

console.log(multiplicar(5, 3)); 
// ReferenceError: Cannot access 'multiplicar' before initialization

let multiplicar = function(a, b) {
    return a * b;
};

En este caso,

  • Se produce un error ReferenceError
  • El error se produce porque la variable multiplicar es elevada, pero la asignación de la función a multiplicar no lo es.
  • Por lo tanto, cuando se intenta llamar a multiplicar antes de la asignación, se obtiene un error porque está en su TDZ
  • Exactamente igual que con una variable que contenga cualquier otro valor