let vs var: ¿guerra de mundos o evolución de JavaScript?
\n\n¿Alguna vez has escrito código en JavaScript y te has sorprendido pensando: «¿Por qué esta variable se comporta de manera tan extraña?» O, peor aún, ¿te has topado con un error que desaparece al reemplazar var por let? Bienvenido al club. La pregunta «What is the difference between "let" and "var"?» en Stack Overflow acumula cientos de miles de visitas no por casualidad: es una de las trampas más comunes para principiantes e incluso desarrolladores experimentados.
Hoy no solo enumeraremos las diferencias. Exploraremos a fondo: entenderemos cómo let y var afectan el rendimiento de tu código, la optimización en motores modernos (V8, SpiderMonkey) y por qué la elección entre ellos no es solo una cuestión de estilo, sino también de eficiencia. Prepárate, se pondrá intenso.
Lo esencial en resumen: ámbito y hoisting (elevación)
\n\nAntes de hablar de rendimiento, recordemos los fundamentos. var y let tienen tres diferencias clave que lo cambian todo.
1. Ámbito (Scope)
\n\n- \n
var— tiene un ámbito de función. Si la variable se declara dentro de una función, es visible en toda la función. Si está fuera, es global. \nlet— tiene un ámbito de bloque. Solo vive dentro de las llaves{}más cercanas (bucle, condición, bloque). \n
// Ejemplo con var\nif (true) {\n var x = 10;\n}\nconsole.log(x); // 10 — la variable "se filtró" del bloque\n\n// Ejemplo con let\nif (true) {\n let y = 20;\n}\nconsole.log(y); // ReferenceError: y is not defined\n\n\n2. Hoisting (elevación) y Zona Muerta Temporal (TDZ)
\n\nAmbas variables se «elevan» (hoisting), pero se comportan de manera diferente.
\n\n- \n
var: la declaración se eleva al inicio del ámbito y se inicializa con el valorundefined. Puedes acceder a la variable antes de su declaración (pero obtendrásundefined). \nlet: la declaración se eleva, pero no se inicializa. Hasta el momento de la declaración real, la variable se encuentra en la «zona muerta temporal» (Temporal Dead Zone). Cualquier acceso a ella provoca unReferenceError. \n
// var — "undefined" seguro\nconsole.log(a); // undefined\nvar a = 5;\n\n// let — error en TDZ\nconsole.log(b); // ReferenceError: Cannot access 'b' before initialization\nlet b = 10;\n\n\n3. Redeclaración
\n\n- \n
var— se puede redeclarar tantas veces como se quiera en el mismo ámbito. No generará error. \nlet— redeclarar en el mismo ámbito provocará unSyntaxError. \n
var z = 1;\nvar z = 2; // Ok\n\nlet w = 1;\nlet w = 2; // SyntaxError: Identifier 'w' has already been declared\n\n\nAhora, lo importante: rendimiento y optimización
\n\nMuchos piensan: «Como let es el nuevo estándar, ¿será más lento que var?» O al contrario: «let es mejor, por lo tanto es más rápido». La verdad, como siempre, está en el medio y depende del contexto.
Cómo optimizan las variables los motores
\n\nLos motores modernos de JavaScript (V8 en Chrome/Node.js, SpiderMonkey en Firefox) compilan el código a código máquina mediante compiladores JIT. Utilizan heurísticas para optimizar.
\n\n- \n
var: debido al ámbito de función y la posibilidad de redefinición accidental, al motor le resulta más difícil hacer suposiciones sobre el tipo de la variable. A menudo crea objetosVariableObject«pesados» que almacenan variables en memoria dinámica. \nlet: el ámbito de bloque y la prohibición de redeclaración le dan al motor b