Hoisting en Javascript

Hoy vamos a hablar del Hoisting, puede ser un poco confuso al principio, pero vamos que es un concepto muy fácil de entender (aunque no se haga referencia en la documentación oficial).

Hoist: Del inglés, significa elevar en castellano, y es la acción que se está realizando (mover las declaraciones al principio).

 ¿Qué es el Hoisting?

Es la acción que realiza Javascript al interpretar, que consiste en mover las declaraciones de variables al inicio de cada ámbito.

Ámbito de variable: Lugar donde están disponibles las variables, en Javascript hay variables locales y globales. Siendo las variables locales las que están entre bloques {…}, excepto en los casos especiales estructuras condicionales o bucles

Permitiendo acceder a las variables antes de definirlas, veamos un ejemplo:

function test() {  
  console.log(a); // undefined
  var a = 5;
}
test();  

Como vemos el resultado es undefined, pero no nos da error porque está definida, pero no tiene ningún valor.
El motivo por el que está sucediendo esto es porque nuestra variable queda definida en lo más alto de nuestro bloque, por eso es recomendable entre otras cosas declarar las variables al inicio de cada bloque, para evitar confusiones.

function test() {  
  var a;
  console.log(a);
  a = 5;
}
test();  

Sería equivalente al funcionamiento del hoisting.

 Juguemos un poco con hoisting

Bueno ahora ya que tenemos claro como funciona, vamos a realizar unas pruebas para ver realmente como se comporta.

Jugando con el Hoisting

  • Variables locales y globales
var a = 'global';  
function test() {  
  console.log(a); // undefined
  var a = 'local';
  console.log(a); // 'local'
}
test();  

Podríamos pensar que el primer console.log imprime el valor global, pero no!, vuelve a pasar lo mismo que en el ejemplo anterior, la variable a aún no tiene ningún valor.
Esto sucede por el hoisting, ya que sería lo mismo que escribir:

var a = 'global';  
function test() {  
  var a;
  console.log(a); // undefined
  a = 'local';
  console.log(a); // 'local'
}
test();  

Ahora vemos claramente que la variable global es ocultada por la local.

  • Comprobamos que los bucles no crean nuevos ámbitos

Como comentábamos, las estructuras condicionales if o bucles for no crean nuevos ámbitos:

function test() {  
  var a = 'global';
  for (i = 0; i < 2; i++) {
    var a = i;
    console.log(a);
  }
  console.log(a); // 1
}
test();  

Podríamos pensar que el último console.log, devolviese el valor global, pero no es así ya que el for no crea un nuevo ámbito por lo que el código equivalente sería el siguiente:

function test() {  
  var a;
  var a;
  var i;
  var a = 'global';
  for (i = 0; i < 2; i++) {
    var a = i;
    console.log(a);
  }
  console.log(a); // 1
}
test();  

Como vemos las variables se generan a nivel de la función y se generan varias definiciones para la misma variable, pero esto en javascript no da error.

Todas estas normas cambian cuando usamos let y const, lo veremos con más detalle en el siguiente artículo del blog

Conclusión

Es importante saber qué es y cómo funciona, para entender el funcionamiento del lenguaje, evitándonos posibles quebraderos de cabeza.