Ámbito de Variables en JavaScript
Aprende los tipos de ámbito en JavaScript: global, de función y de bloque, y cómo las funciones anidadas acceden a variables externas mediante la cadena de ámbito.
El ámbito es la parte de un programa donde una variable es visible y puede usarse. Comprender el ámbito es lo que permite predecir a qué valor hace referencia un nombre, evitar colisiones accidentales entre variables y razonar sobre por qué una variable está o no disponible en un punto determinado. Esta guía explica los tipos de ámbito que tiene JavaScript, cómo las funciones anidadas acceden a los ámbitos que las rodean, en qué se diferencia var de let/const, y cómo todo esto conduce naturalmente a los closures.
Los tres tipos de ámbito
JavaScript determina la visibilidad de las variables en función de dónde se declara la variable en el código fuente — esto se denomina ámbito léxico (o estático). Existen tres niveles:
- Ámbito global — declarado fuera de cualquier función o bloque. Visible en todas partes.
- Ámbito de función — declarado dentro de una función. Visible únicamente dentro de esa función (así es como funciona
var). - Ámbito de bloque — declarado con
letoconstdentro de un bloque{ ... }(unif, unforo incluso un{}vacío). Visible únicamente dentro de ese bloque.
Ámbito global
Una variable declarada en el nivel superior de un script es global: cualquier función y bloque puede leerla y escribirla.
Las variables globales son convenientes pero arriesgadas: cualquier parte del programa puede modificarlas, y dos fragmentos de código no relacionados pueden usar el mismo nombre y sobreescribirse mutuamente. Mantén el espacio de nombres global lo más pequeño posible.
Ámbito de función
Una variable declarada dentro de una función existe solo mientras esa función se ejecuta y es invisible desde el exterior.
El bloque try...catch permite que el ejemplo continúe ejecutándose para que puedas ver el mensaje de error en lugar de que el script simplemente se detenga.
Ámbito de bloque
let y const tienen ámbito limitado al bloque delimitador más cercano, no a toda la función. Una variable declarada dentro de un bloque if o for desaparece una vez que el bloque termina.
Cómo las funciones anidadas ven las variables externas
Cuando anidas funciones, la función interna puede leer variables de todos los ámbitos que la rodean: el suyo propio, el de la función contenedora y el ámbito global. Esta cadena de ámbitos accesibles se denomina entorno léxico (o cadena de ámbitos).
Cuando JavaScript busca un nombre, comienza en el ámbito actual y avanza hacia afuera hasta encontrar la variable. Si llega al ámbito global sin encontrarla, obtienes un ReferenceError.
La búsqueda solo va hacia afuera, nunca hacia adentro — outer() no puede ver innerVar. Este es exactamente el mecanismo que hace que los closures funcionen: una función interna mantiene acceso a sus variables externas incluso después de que la función externa haya retornado.
var vs let y const
Las reglas de ámbito difieren según cómo declares una variable. var tiene ámbito de función e ignora los bloques, mientras que let y const tienen ámbito de bloque. Esta es una de las fuentes más comunes de errores en el código antiguo.
La trampa clásica es un bucle que crea callbacks. Con var hay una sola variable compartida; con let, cada iteración obtiene su propio enlace:
Para un análisis más profundo de las peculiaridades de var — incluyendo el hoisting y la falta de ámbito de bloque — consulta el antiguo "var".
Hoisting y la Zona Muerta Temporal
Las declaraciones se procesan antes de que se ejecute el código. Una declaración con var es elevada (hoisted) e inicializada como undefined, por lo que leerla antes de la asignación devuelve undefined en lugar de un error. let y const también se elevan, pero permanecen en una Zona Muerta Temporal (TDZ) — inutilizables hasta que se ejecuta la línea que las declara.
Buenas prácticas
- Prefiere
const, luegolet, evitavar. El ámbito de bloque es más predecible y evita fugas accidentales y la trampa del bucle con callbacks mostrada anteriormente. - Mantén las variables en el ámbito más estrecho que funcione. Declara dentro del bloque o función que las necesita, en lugar de hacerlo en el nivel superior.
- Minimiza las variables globales. Menos variables globales significa menos colisiones de nombres y menos valores que cualquier código puede modificar silenciosamente.
- Declara antes de usar. Aunque existe el hoisting, depender de él hace que el código sea más difícil de leer.
Conclusión
El ámbito controla dónde es visible cada variable: global, de función o de bloque. Las funciones anidadas forman un entorno léxico que permite que el código interno acceda hacia afuera a través de la cadena de ámbitos — la base de los closures. Elegir let/const sobre var proporciona un ámbito de bloque confiable y evita sorpresas por hoisting. A continuación, estudia cómo las funciones capturan su entorno en JavaScript Closures y cómo se comportan las funciones retornadas en las expresiones de función.