Recientemente un viejo colega (@f5inet) me pedÃa una breve introducción al uso de las variables en Javascript. Explicándole por encima las normas básicas, llegué a uno de los puntos que más confusión despiertan y que son una fuente frecuente de errores para los programadores noveles: el hoisting.
El hoisting (“elevación”) en Javascript es una de esas particularidades del lenguaje sobre la que la comunidad de desarrolladores no llega a ponerse de acuerdo en si se trata de un bug o una feature.
Para John Resig, manejado correctamente, es un poderoso aliado a la hora de gestionar los ámbitos que alcanzan nuestras variables; para otros como Douglas Crackford, su descuido se convierte inmediatamente en inconsistencias en nuestros códigos y errores potenciales difÃciles después de identificar y depurar.
Qué es el hoisting?
En Javascript, cuando se define una variable en el interior de una función, el intérprete interno pasa a ubicarla al comienzo de su contexto (la eleva). Podemos imaginarnos asà a nuestras funciones como recipientes de agua hirviendo donde las partÃculas más pequeñas (las variables) buyen hacia la superficie; el resto de elementos, incluidos los valores de esas variables, son más pesados y se quedan donde están.
Ejemplos
Tomemos el siguiente código:
function foo(){ bar(); var x = 1; } |
Pese a que hemos declarado la variable x un punto concreto del código, el intérprete Javascript mueve dicha declaración a lo más alto de su contexto. Internamente, el código se ejecutarÃa de la siguiente manera:
function foo(){ var x; bar(); x = 1; } |
La variable es declarada antes que se ejecute cualquier otra acción, lo que puede llegar a ocasionar comportamientos no esperados:
var x = 'Hello World'; // variable global function foo(){ alert( x ); // esperamos el valor global var x = 'New Value'; // redefinimos la variable en contexto local alert( x );Â // esperamos el nuevo valor local } foo(); |
Posiblemente este código no funcione como se deseábamos: el primer alert() no devuelve el valor ‘Hello World’ pese a que la variable habÃa sido declarada anteriormente como global. En su lugar, obtenemos un inesperado undefined. La razón es que la posterior declaración de x, internamente se eleva hasta el inicio de su función (buye), por lo que pasa a estar definida de forma local pero sin un valor aún asignado. El anterior código equivale a este mucho más claro:
var x = 'Hello World'; function foo(){ var x; alert( x ); x = 'New Value'; alert( x ); } foo(); |
La recomendación de los expertos es siempre declarar las variables locales al principio de su actual ámbito para evitar errores. De esta forma ganamos además legibilidad del código ya que agrupamos asà todas nuestras variables en un mismo lugar permitiéndonos de un vistazo conocer el tipo de datos que esperan:
function foo(){ var myObj = {}; var myArray = []; var number1, number2, number3; var string1, string2, string3; // Some code here... } |
Como apunte final, aclarar que el término hoisting no está definido dentro del actual ECMAScript, sin embargo es comunmente utilizando para describir el particular comportamiento que Javascript hace de las variables en el interior de las funciones.

Pingback: Entendiendo el hoisting en Javascript - apezz.com
Muy interesante tu blog.
Lo acabo de descubrir accidentalmente…
Un remedio de la abuela, la que fuma, para evitar accidentes como el de tu segundo ejemplo es usar el ámbito al referirse a una variable declarada globalmente, fuera de una función.
En este caso alert(window.x).
Hola David;
efectivamente, si la idea es referirse a la variable global, podemos acceder a ella a través del objeto window (contexto general del navegador).
Sin embargo, la idea aquà es no confundirse con el ámbito en el que se declaran las variables para asà evitar comportamientos raros
Tú ejemplo quedarÃa:
var a = 'foo'; (function hola(){ console.log( window.a ); // foo var a = 'bar'; console.log( a ); // bar })();Un saludo!
Bendito namespacing de todos modos…