¿Qué es Hoisting en Javascript? - El Mundo de Angular

¿Qué es Hoisting en Javascript?

¿Por qué parece que Javascript hace lo que quiere? ¿Por qué hay cosas que no tienen sentido? Si yo hago lo mismo con otro lenguaje de programación el código me explota por los aires, pero con Javasript no, con Javascript el código sólo se comporta extraño. No me arroja un error, no se comporta como yo espero, solo se comporta «raro».

El problema

¿A qué me refiero? Si tengo por ejemplo el siguiente código Javascript:


function b() {
    console.log('llamando a b!');
}

console.log(a);

var a = 'Hola Mundo!';

b();

Si te fijás bien, en el ejemplo la variable «a» es inicializada después de ser usada (o ejecutada). En cualquier otro lenguaje de programación esto arrojaría un error, peeeero… adiviná qué: en Javascript el código no arroja ningún error. Es más, el código funciona e imprime lo siguiente en consola:

«called b!»
undefined

 

¿Tiene sentido para vos? ¿Tiene sentido que el motor te deje usar una variable ANTES de haberla creado? Y además, ¿qué significa ese «undefined«, que no hace falta definir las variables que usamos? y si eliminamos completamente la creación de la variable… ¿nuestro código seguirá funcionando?


function b() {
    console.log('called b!');
}

console.log(a);

b();

 

Nop, eso nos arroja un error

Uncaught ReferenceError: a is not defined

Eso nos está diciendo que la variable «a» no está definida, lo cual es cierto ya que eliminamos la definición.

Y entonces, ¿por qué es obligatorio definir una variable pero no es obligatorio hacerlo ANTES de usar esa variable en nuestro código?

Esto es asi porque el motor de Javascript, cuando crea el Execution Context (o contexto de ejecución), éste se hace en 2 partes: Fase de Creación y Fase de Ejecución.

En la primera fase, la Fase de Creación del Execution Context, creamos todas las variables y funciones, PERO no las ejecutamos, de hecho al crearlas, por defecto, se le asigna la palabra reservada ‘undefined’. En el siguiente código:


var a = 'hola mundo';
var f = function() {
    console.log('hola mundo')
}

Al finalizar la etapa de creación del Execution Context ambas variables («a» y «f») valen ‘undefined’.

Recién en la etapa de ejecución es en donde se le asignan valores a nuestras variables, y se ejecuta nuestro código también.

Hoisting

Hoisting es reservar espacio en memoria para todas tus variables. Esto se hace en la etapa de creación de tu Execution Context. Lo que hace el motor de Javascript es escanear todo tu código e ir buscando las declaraciones de todas tus variables; cuando encuentra una nueva variable reserva espacio en memoria y le asigna el valor «undefined«. Undefined es un valor en Javascript que indica que la variable no fue inicializada.

Es por eso que podemos usar una variable que ha sido declarada más adelante en nuestro código y que el valor que tiene es «undefined».

 

Y ahora, las cosas «raras» que pasan en Javascript

¿Y qué consecuencias o comportamientos extraños nos puede traer esta característica de Javascript?: Hoisting

Para empezar podemos hacer esto:


console.log(a);
var a = 'hola mundo';

Aunque en otros lenguajes de programación esto arrojaría un error, en Javascript se puede hacer y, no sólo no arroja ningún error, sino que imprime algo en consola. ¿Te imaginás qué imprime?

¡Exacto! Imprime ‘undefined’ ya que en la Fase de Creación del Execution Context se inicializó con ese valor.

¿Y qué pasa con las funciones que guardamos en variables?

Pasa algo parecido, si tenemos este código:


f();
var f = function() {
    console.log('hola mundo')
}

¿Qué te parece? ¿este código explota?…

Sí, explota, pero… no explota porque «f «no está definida, el error es el siguiente:

Uncaught TypeError: f is not a function

Ésto nos está diciendo que «f» no es una función, pero qué raro ¿no? porque ¡sí es una función! Lo que está pasando es que en el momento en que se está ejecutando el código, la variable «f» vale ‘undefined’ (que es el valor por defecto que se le asigna a todas las variables que se crean en la Fase de Creación de cualquier Execution ContextB), entonces, lo que se está haciendo en el código es ejecutar un valor que vale ‘undefined’ como si fuera una función, y ese es el error que se imprime en consola:

Uncaught TypeError: f is not a function

 

Y te podrías preguntar, bueno… ¿por qué ya que en la etapa de creación de un Execution Context se reserva espacio en memoria, no me asigna el valor a la variable?

Porque la asignación de valores corresponde a la etapa de Ejecución, y como Javascript ejecuta tu código línea por línea, si lo primero que encuentra es ésto:


f();

Y después encuentra lo siguiente:



var f = function() {
    console.log('hola mundo')
}


Lo primero que va a hacer es ejecutar tu función, o al menos intentar hacerlo.

 

Una forma de ver este problema, es pensarlo como lo ve Javascript (en 2 etapas):

Conclusión

La forma de evitar los problemas Hoisting es definiendo tus variables al inicio de tu función, o de tu archivo principal, si estás en el archivo principal. De esta forma, te aseguras que definís e inicializás tus variables antes de hacer cualquier otra cosa. ¡Suerte! y ¡cuidado con el Hoisting!

About the Author

Mi nombre es Gustavo Hernán Dohara, soy Ingeniero en Sistemas y, sobre todas las cosas, soy un apasionado por la tecnología; tengo más de 10 años de experiencia en diferentes tecnologías y he decidido compartir mis conocimientos y experiencias con cualquiera que desee aprender: alumnos, empleados, freelancers y vos. Al ritmo que cada uno pueda, en el horario en que cada uno pueda y en el lugar que cada uno elija.

 ¡OFERTA! 

 101 Preguntas Sobre javascript

Que te Harán En Cualquier Entrevista (Con Sus Respuestas)