¿Qué significa el shadowing en JavaScript? Con ejemplos!
El shadowing en JavaScript significa que una variable declarada en un ámbito más interno oculta otra con el mismo nombre en un ámbito superior. Sus características pueden generar confusión si no se comprende bien su alcance. Con un buen ejemplo, verás cómo afecta tu código y cómo evitar errores inesperados. ¡Continua explorando!

Índice
1. ¿Qué es el shadowing en JavaScript?
En JavaScript, el «shadowing» (o «sombreado») ocurre cuando una variable declarada dentro de un cierto ámbito (scope) tiene el mismo nombre que una variable declarada en un ámbito exterior.
La variable del ámbito interior «sombra» o «oculta» a la variable del ámbito exterior, impidiendo que esta última sea accedida directamente desde el ámbito interior.
1.1. Veamos un ejemplo sencillo de shadowing:
let nombre = "Juan"; // Variable en el ámbito global
function saludar() {
let nombre = "María"; // Variable en el ámbito de la función (sombra a la variable global)
console.log(nombre); // Imprime: "María" (la variable del ámbito local)
}
saludar();
console.log(nombre); // Imprime: "Juan" (la variable global no fue modificada)
Lenguaje del código: JavaScript (javascript)
¿Que sucede aquí?
- En este ejemplo, tenemos dos variables llamadas
"nombre":- Una en el ámbito global
- Otra dentro de la función
saludar.
- Dentro de la función…….la variable
"nombre"local «sombra» a la variable global, por lo queconsole.log(nombre)imprime «María». - Fuera de la función………la variable global
"nombre"sigue existiendo y su valor no ha sido modificado.
NOTA!!!! Si te animas y deseas ver el resultado de este ejemplo y de todos los que iremos proporcionando directamente desde tu PC, te invito a seguir estos pasos.
- Primero, revisa el punto 5 del siguiente artículo sobre como usar e instalar VSCode (este es el editor de código mas usado), donde encontrarás los pasos para crear la estructura necesaria para visualizar una página desde tu navegador predeterminado.
- Si entendiste correctamente este paso anterior, sabrás donde colocar el código
scriptque te acabamos de proporcionar (arriba). Ahora, puedes visualizar el resultado, para ello puedes hacer lo siguiente:- Una vez abierta y visualizada la página, abre la consola del navegador presionando la tecla F12.
- Ahora, dirígete a la pestaña que dice
Console, y desde aquí podrás ver el resultado del script que hayamos introducido anteriormente.
- No te preocupes, estos pasos son más simples de lo que parecen!!!! Entonces… cada vez que dejemos un código de ejemplo como éste, puedes seguir estos pasos y ver los resultados por ti mismo. ¡Ojalá te animes!!!!
1.2. ¿Por qué es útil el shadowing?
🚨 ENCAPSULAMIENTO:
Permite crear variables locales dentro de funciones o bloques de código sin preocuparse por si existen variables con el mismo nombre en otros ámbitos. Esto ayuda a mantener el código más organizado y evita conflictos de nombres.
🚨 ABSTRACCIÓN:
Facilita la creación de funciones o módulos que utilizan variables internas sin exponerlas al exterior. El usuario de la función no necesita conocer los detalles de las variables internas, lo que simplifica su uso.
1.3. Consideraciones importantes:
1️⃣ SE BASA EN EL ÁMBITO LÉXICO:
El shadowing se basa en el ámbito léxico (o estático) de JavaScript. Esto significa que el ámbito de una variable se determina por su posición en el código fuente, no por cómo se ejecuta el programa.
2️⃣ var, let y const:
Las palabras clave var, let y const tienen diferentes reglas de ámbito. var tiene un ámbito de función o global, mientras que let y const tienen un ámbito de bloque. Esto afecta cómo se aplica el shadowing en cada caso.
Ampliemos estas consideraciones!!!
2. El ámbito léxico y su relaciona con el «shadowing» en JS.
2.1. ¿Qué es el ámbito léxico (o estático)?
El ámbito léxico, también conocido como ámbito estático, es una regla que define la accesibilidad de las variables en función de su ubicación física en el código fuente. En otras palabras, el ámbito de una variable se determina analizando la estructura del código, no cómo se ejecuta el programa en tiempo real.
2.2. ¿Cómo funciona el ámbito léxico?
- Análisis del código fuente:
- El intérprete de JavaScript analiza el código fuente y crea un árbol de «entornos léxicos». Cada función o bloque de código (definido por llaves
{}) crea su propio entorno léxico.
- El intérprete de JavaScript analiza el código fuente y crea un árbol de «entornos léxicos». Cada función o bloque de código (definido por llaves
- Encadenamiento de entornos:
- Los entornos léxicos se encadenan entre sí, formando una jerarquía. Un entorno interno puede acceder a las variables de su entorno externo, y así sucesivamente hasta llegar al entorno global.
- Resolución de variables:
- Cuando se utiliza una variable, JavaScript busca su declaración en el entorno léxico actual. Si no la encuentra, busca en el entorno léxico externo, y así sucesivamente hasta encontrarla en el entorno global.
2.3. ¿Cómo se relaciona el shadowing y ámbito léxico?
El «shadowing» es una consecuencia directa del ámbito léxico, siendo este ámbito léxico lo que nos brinda el concepto sobre shadowing que dimos en el punto 1:
«Cuando se declara una variable dentro de un entorno interno con el mismo nombre que una variable en un entorno externo, la variable interna «sombra» a la externa dentro de ese entorno interno. «
Esto se debe a que JavaScript, al buscar una variable, prioriza el entorno léxico más cercano.
2.4. Ejemplo para ilustrar el ámbito léxico y el shadowing:
let nombre = "Juan"; // Variable en el ámbito global
function saludar() {
let nombre = "María"; // Variable en el ámbito de la función (sombra a la variable global)
console.log(nombre); // Imprime: "María" (la variable del ámbito local)
function mostrarApellido() {
let apellido = "Pérez"; // Variable en el ámbito de la función interna
console.log(nombre + " " + apellido); // Imprime: "María Pérez" (accede a la variable 'nombre' del ámbito externo de la función saludar)
}
mostrarApellido();
}
saludar();
console.log(nombre); // Imprime: "Juan" (la variable global no fue modificada)
Lenguaje del código: JavaScript (javascript)
En este ejemplo:
- La variable
nombreglobal está disponible en todos los ámbitos. - Dentro de la función
saludar, se declara una nueva variablenombreque «sombra» a la global. - La función interna
mostrarApellidotiene acceso a su propio entorno léxico, al desaludar(donde encuentra la variablenombre) y al global.
2.5. Importancia del ámbito léxico
El ámbito léxico es fundamental para entender cómo funciona JavaScript y cómo se organizan las variables en el código. Permite crear código más modular, encapsulado y predecible.
3. Shadowing con var, let y const
3.1. Shadowing con var
La palabra clave var tiene ámbito de función, lo que significa que si declaras una variable var dentro de una función, esa variable será accesible solo dentro de esa función.
Sin embargo, si var está en un bloque {} (como en un if, for o while), la variable sigue siendo global (o pertenece a la función más cercana).
Veámoslo con un ejemplo:
var nombre = "Pedro";
if (true) {
var nombre = "Juan";
console.log(nombre); // Imprime: "Juan" (Modifica la variable global)
}
console.log(nombre); // Imprime: "Juan" (Se alteró la variable global)Lenguaje del código: JavaScript (javascript)
Explicación paso a paso:
- Se declara
var nombre = "Pedro";, que pertenece al ámbito global. - Dentro del bloque
if,var nombre = "Juan";no crea una nueva variable dentro del bloque, sino que reemplaza la variable global. - Cuando hacemos
console.log(nombre);dentro delif, imprime"Juan"porque la variable ya fue modificada. - Después del
if,console.log(nombre);sigue mostrando"Juan"porque se sobrescribió la variable global.
🔴 PROBLEMA: Se esperaba que la variable nombre solo cambiara dentro del if, pero terminó modificando el valor global, lo que puede causar comportamientos inesperados y errores difíciles de depurar.
3.2. Shadowing con let y const (Buena Práctica)
A diferencia de var, las variables declaradas con let y const tienen ámbito de bloque, lo que significa que no sobrescriben variables globales cuando se usan dentro de bloques {}. Esto hace que el código sea más seguro y predecible.
Veámoslo con un ejemplo:
let edad = 30;
if (true) {
let edad = 25;
console.log(edad); // Imprime: "25" (Ámbito local)
}
console.log(edad); // Imprime: "30" (No se alteró la variable global)Lenguaje del código: JavaScript (javascript)
Explicación paso a paso:
- Se declara
edad = 30en el ámbito global. - Dentro del
if, se declara otra variableedad = 25usandolet:- Esta variable es completamente nueva y existe solo dentro del bloque
{}. - No sobrescribe la variable global:
- Cuando ejecutamos
console.log(edad);dentro delif, obtenemos"25", porque la variable local tiene prioridad sobre la global dentro del bloque. - Cuando salimos del bloque
if, la variableedaddentro del bloque deja de existir, por lo queconsole.log(edad);fuera delifimprime"30", el valor de la variable global.
- Cuando ejecutamos
- Esta variable es completamente nueva y existe solo dentro del bloque
3.3. Conclusión: ¿Por qué let y const son más seguros para el shadowing?
✔ Evitan la sobrescritura accidental de variables globales.
✔ Facilitan la comprensión del código, ya que las variables tienen un alcance bien definido.
✔ Reduce errores difíciles de depurar causados por la reasignación inesperada de valores.
💡 REGLA DE ORO: Siempre usá let o const en lugar de var para evitar efectos no deseados con el shadowing.
4. Shadowing y this en JavaScript
El uso de this en JavaScript puede cambiar según el contexto en el que se ejecuta, lo que puede provocar shadowing accidental.
4.1. ¿Qué es this en JavaScript?
En JavaScript, this es una referencia al objeto que está ejecutando la función en ese momento.
- En el ámbito global,
thishace referencia al objetowindow(en navegadores). - Dentro de un objeto,
thisapunta al objeto que lo contiene. - Dentro de una función regular, el valor de
thisdepende de cómo se llame la función. - En funciones flecha (
=>),thisno se redefine y mantiene el valor del contexto en el que fue creada.
4.2. ¿Cómo se relaciona this con el shadowing?
El shadowing ocurre cuando una variable local sombréa una variable de nivel superior. Entonces, cuando el shadowing pasa con this, el código puede comportarse de manera inesperada.
📌 EJEMPLO de Shadowing accidental con this
const usuario = {
nombre: "Alejandro",
edad: 35,
mostrarInfo: function () {
console.log(this.nombre); // "Alejandro"
function interna() {
console.log(this.nombre); // ❌ `undefined` en modo estricto o "window.nombre" en modo no estricto
}
interna(); // Llamada a una función regular (cambia el contexto de `this`)
}
};
usuario.mostrarInfo();Lenguaje del código: JavaScript (javascript)
Explicación del problema:
- Dentro de
mostrarInfo,thishace referencia al objetousuario, por lo quethis.nombredevuelve"Alejandro". - Dentro de la función
interna(),thisya no apunta al objetousuario, sino al objeto global (windowen navegadores,undefineden modo estricto). - Como
window.nombreno existe, devuelveundefined.
4.3. Conclusión:
- El shadowing con
thisocurre cuandothiscambia de contexto inesperadamente. - Las funciones regulares cambian el valor de
this, lo que puede generar errores. - Soluciones:
- Guardar
thisen una variable (self = this). - Usar funciones flecha (
=>), ya que heredan el valor dethisdel contexto donde fueron creadas.
- Guardar
📌 REGLA DE ORO: Evitá usar this dentro de funciones anidadas regulares y preferí las funciones flecha o self = this para evitar shadowing accidental.
5. Complicaciones comunes del Shadowing en JavaScript.
Si no tenés presente el shadowing, podés encontrarte con varios problemas en tu código, algunos difíciles de depurar.
Aquí te detallo los más comunes:
- Modificación accidental de variables globales (
var)- Si usás
var, el shadowing puede sobrescribir variables globales sin darte cuenta.
- Si usás
thisapunta a un contexto inesperado- Si
thiscambia de contexto inesperadamente, podés obtener resultados inesperados, especialmente en funciones dentro de objetos.
- Si
- Variables en loops (
for) se sobrescriben inesperadamente- Cuando usás
varen loops, todas las iteraciones comparten la misma variable, lo que puede dar resultados inesperados. - Ejemplo de problema con
varen un loop:
- Cuando usás
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// ❌ Imprime: 3, 3, 3 (porque `var i` es global y al finalizar el loop vale 3)Lenguaje del código: JavaScript (javascript)
✅ Solución: Usar let, que tiene ámbito de bloque.
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// ✅ Imprime: 0, 1, 2 (cada iteración tiene su propia variable `i`)Lenguaje del código: JavaScript (javascript)
- Parámetros de función que hacen shadowing
- Si usás el mismo nombre de variable dentro de una función, podés ocultar el parámetro sin darte cuenta.
- Ejemplo de problema con shadowing en parámetros:
function saludar(nombre) {
let nombre = "Carlos"; // ❌ Shadowing del parámetro
console.log("Hola, " + nombre);
}
saludar("Pedro"); // ❌ Error: Identifier 'nombre' has already been declaredLenguaje del código: JavaScript (javascript)
✅ Solución: Evitar redeclarar variables con el mismo nombre de los parámetros.
function saludar(nombre) {
let saludo = "Carlos"; // ✅ No hay shadowing del parámetro
console.log("Hola, " + nombre);
}
saludar("Pedro"); // "Hola, Pedro"Lenguaje del código: JavaScript (javascript)
- Problemas con el scope en funciones anidadas
- Si una función interna usa el mismo nombre de variable que una función externa, se puede generar confusión.
- Ejemplo de problema con funciones anidadas
function externa() {
let mensaje = "Hola desde externa";
function interna() {
let mensaje = "Hola desde interna"; // ❌ Shadowing
console.log(mensaje);
}
interna();
console.log(mensaje);
}
externa();
// ✅ Imprime:
// "Hola desde interna"
// "Hola desde externa"Lenguaje del código: JavaScript (javascript)
En este caso, el shadowing no causa errores, pero puede ser confuso porque hay dos variables mensaje con valores distintos.
✅ Solución: Usar nombres más descriptivos para evitar confusión.
function externa() {
let mensajeExterno = "Hola desde externa";
function interna() {
let mensajeInterno = "Hola desde interna";
console.log(mensajeInterno);
}
interna();
console.log(mensajeExterno);
}Lenguaje del código: JavaScript (javascript)
6. Recomendaciones teniendo en cuenta el shadowing.
6.1. Usa let o const en lugar de var
- Problema con
var: Las variables declaradas convartienen un ámbito de función o global, lo que puede llevar a «shadowing» accidental en lugares inesperados. - Solución con
letyconst:letyconsttienen un ámbito de bloque, lo que significa que están limitadas al bloque de código (definido por llaves{}) donde se declaran. Esto reduce drásticamente el riesgo de «shadowing» no intencionado.
Ejemplo:
function ejemplo() {
var x = 10; // Ámbito de función
if (true) {
let x = 20; // Ámbito de bloque (esta 'x' no afecta a la 'x' de arriba)
console.log(x); // Imprime 20
}
console.log(x); // Imprime 10 (la 'x' del ámbito de función no fue modificada)
}
Lenguaje del código: JavaScript (javascript)
6.2. Evita nombres de variables genéricos
- Problema: Usar nombres como
data,valueotemppuede llevar a confusiones y «shadowing» accidental, especialmente en funciones o bloques de código anidados. - Solución: Elige nombres descriptivos que indiquen claramente el propósito de la variable.
Ejemplo:
// Mal
function procesar(data) {
let temp = data * 2;
return temp;
}
// Bien
function calcularAreaRectangulo(longitud, ancho) {
let area = longitud * ancho;
return area;
}
Lenguaje del código: JavaScript (javascript)
6.3. Especifica nombres claros para parámetros y variables internas
- Problema: Si los parámetros de una función o las variables internas tienen nombres poco claros, es más fácil confundirlos con variables de ámbitos exteriores y caer en «shadowing» no deseado.
- Solución: Utiliza nombres descriptivos y significativos para parámetros y variables.
Ejemplo:
function calcularImpuestos(ingresoBruto) {
let tasaImpuesto = 0.15; // Variable interna clara
let impuesto = ingresoBruto * tasaImpuesto;
return impuesto;
}
Lenguaje del código: JavaScript (javascript)
6.4. Mantén ámbitos de variables lo más pequeños posible
- Problema: Cuanto más amplio sea el ámbito de una variable, mayor es la probabilidad de que cause «shadowing» en ámbitos internos.
- Solución: Declara las variables lo más cerca posible de donde se utilizan. Esto reduce el riesgo de «shadowing» accidental y mejora la legibilidad del código.
Ejemplo:
function calcularPromedio(numeros) {
let suma = 0; // Variable con ámbito limitado a la función
for (let i = 0; i < numeros.length; i++) {
suma += numeros[i];
}
let promedio = suma / numeros.length;
return promedio;
}Lenguaje del código: JavaScript (javascript)
7. Preguntas frecuentes y resumen sobre shadowing en JS.
El shadowing ocurre cuando una variable en un ámbito interno tiene el mismo nombre que otra en un ámbito externo, ocultándola dentro del bloque interno. JavaScript usará la variable más cercana en el alcance, ignorando la externa dentro del mismo contexto.
El shadowing limita el acceso a variables externas dentro de un bloque interno si tienen el mismo nombre. Esto puede generar confusión al acceder a valores, ya que el motor de JavaScript prioriza la variable más cercana dentro del mismo ámbito.
Para evitar el shadowing, usa nombres de variables descriptivos, evita reutilizar identificadores en distintos ámbitos y usa const y let en lugar de var para definir variables con alcance de bloque, reduciendo la posibilidad de sobreescritura accidental.
Los errores comunes incluyen la sobrescritura accidental de valores, dificultades para depurar código cuando variables esperadas no contienen los datos correctos y problemas con el uso de var, que permite shadowing a nivel de función en lugar de bloque.
El alcance léxico dicta que JavaScript busca variables en el bloque donde se usan y en sus ámbitos superiores. Si hay shadowing, el motor de JavaScript usa la variable más cercana en la jerarquía de alcance, ignorando las de ámbitos superiores.
El hoisting puede hacer que una variable declarada con var en un bloque se eleve al inicio de su función, causando shadowing inesperado. Con let y const, el hoisting ocurre pero las variables quedan en la «zona temporal muerta» hasta su declaración.
Evita nombres genéricos para variables, usa let y const en vez de var, organiza tu código con funciones bien delimitadas y revisa si es necesario redefinir variables dentro de bloques internos.
