En JavaScript, tanto var, let como const experimentan hoisting, es decir, sus declaraciones son "elevadas" al inicio de su ámbito durante la fase de creación del motor de JavaScript. Sin embargo, la gran diferencia radica en cómo se manejan antes de su inicialización explícita en el código. Mientras que var se inicializa automáticamente con undefined, las variables declaradas con let y const quedan atrapadas en una "Zona Muerta Temporal" (TDZ), un estado en el que existen pero no son accesibles hasta que el flujo del programa llega a su declaración. Intentar usarlas antes de ese momento genera un ReferenceError.
La TDZ es una región del código que abarca desde el inicio del ámbito (donde la variable es "elevada") hasta el punto exacto donde se declara e inicializa con let o const. Durante esta "zona muerta", la variable está registrada en el entorno léxico del ámbito, pero JavaScript prohíbe cualquier acceso a ella para evitar comportamientos impredecibles o errores de lógica. Esto es un diseño intencional introducido en ECMAScript 6 (ES6) para mejorar la seguridad y claridad del lenguaje.
La TDZ resuelve problemas heredados de var, como el acceso accidental a variables no inicializadas (que devuelven undefined y pueden ocultar errores). Con let y const, el TDZ fuerza a los desarrolladores a ser más explícitos y estructurados en la declaración de variables, reduciendo bugs sutiles. Sin embargo, también exige una comprensión clara del flujo del código, ya que ignorar la TDZ puede llevar a errores inesperados en tiempo de ejecución.
console.log(x); // ❌ ReferenceError: Cannot access 'x' before initialization
let x = 5;
console.log(x); // 5
Análisis paso a paso:
let x en el ámbito, pero no la inicializa. Aquí comienza la TDZ de x.x con console.log(x), JavaScript detecta que está en la TDZ y lanza un ReferenceError.let x = 5, la TDZ termina y x es accesible con el valor 5.Contraste con var:
console.log(y); // undefined
var y = 10;
console.log(y); // 10
Con var, no hay TDZ: la variable se inicializa como undefined desde el inicio.
{
console.log(z); // ❌ ReferenceError: Cannot access 'z' before initialization
let z = 20;
console.log(z); // 20
}