Last modified: Jul 17, 2026
JavaScript Variable Shadowing
Variable shadowing is a common concept in JavaScript. It happens when a variable in an inner scope has the same name as a variable in an outer scope. The inner variable "shadows" the outer one. This can cause confusion for beginners. Understanding it is key to writing clean code.
In this article, we will explain what shadowing is. We will show examples with var, let, and const. We will also share tips to avoid bugs. Let's dive in.
What Is Variable Shadowing?
Variable shadowing occurs when you declare a variable with the same name in a nested scope. The inner variable takes precedence. It blocks access to the outer variable. This is a natural result of JavaScript's scope rules.
Think of it like a shadow. When you stand in the sun, your shadow covers the ground. The inner variable is like your shadow. It covers the outer variable. You can still see the outer one, but the inner one is in the way.
How Shadowing Works with Different Declarations
JavaScript has three ways to declare variables: var, let, and const. Each behaves differently with shadowing.
Shadowing with var
The var keyword has function scope. It is not block-scoped. This means shadowing with var can be tricky. It can cause unexpected results.
// Example with var
var name = "Global";
function showName() {
var name = "Local"; // This shadows the global name
console.log(name); // Output: Local
}
showName();
console.log(name); // Output: Global
In this example, the name inside the function shadows the global name. The function prints "Local". Outside, it prints "Global". This works as expected.
But var is not block-scoped. So shadowing inside a block like an if statement can cause issues.
// var is not block-scoped
var x = 10;
if (true) {
var x = 20; // This does NOT shadow; it reassigns
console.log(x); // Output: 20
}
console.log(x); // Output: 20 (global changed)
Here, var x inside the block does not create a new variable. It changes the global x. This is not true shadowing. It is a common pitfall. To avoid this, use let or const.
Shadowing with let and const
The let and const keywords are block-scoped. They create a new variable in each block. This makes shadowing more predictable.
// Example with let
let count = 100;
if (true) {
let count = 200; // This shadows the outer count
console.log(count); // Output: 200
}
console.log(count); // Output: 100
In this example, the inner count is a new variable. It shadows the outer one. The outer count remains unchanged. This is clean and safe.
The same works for const. But remember, const cannot be reassigned. Shadowing still works because it is a new variable.
// Example with const
const pi = 3.14;
if (true) {
const pi = 3.14159; // New variable, shadows outer pi
console.log(pi); // Output: 3.14159
}
console.log(pi); // Output: 3.14
Why Shadowing Can Be Dangerous
Shadowing is not always bad. But it can cause bugs. If you forget about the outer variable, you might use the wrong value. This is especially common in loops and callbacks.
Consider a loop with a function. The loop variable might be shadowed. This can lead to unexpected behavior.
// Loop shadowing issue
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // Output: 3, 3, 3
}, 100);
}
Here, var i is hoisted. All callbacks share the same i. By the time they run, i is 3. To fix this, use let for block scoping.
// Fixed with let
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // Output: 0, 1, 2
}, 100);
}
With let, each iteration gets its own i. The shadowing is intentional and correct.
Best Practices to Avoid Shadowing Bugs
Follow these tips to use shadowing safely. They will help you write cleaner code.
1. Use let and const instead of var. They have block scope. This makes shadowing predictable. It reduces bugs.
2. Avoid reusing variable names in nested scopes. Give each variable a unique name. This improves readability. It also prevents accidental shadowing.
3. Keep functions small. A small function has fewer scopes. This reduces the chance of shadowing. It also makes code easier to test.
4. Use linters. Tools like ESLint can warn you about shadowing. They help you catch issues early. This is a great practice for teams.
5. Understand your scope. Know where your variables live. Review the JavaScript Variable Scope Explained guide for more details. This knowledge is power.
Real-World Example of Shadowing
Let's look at a practical example. Imagine you have a configuration object. You might have a global variable and a local one.
// Real-world example
const config = { theme: "dark" };
function updateConfig() {
const config = { theme: "light" }; // Shadows global config
console.log(config.theme); // Output: light
}
updateConfig();
console.log(config.theme); // Output: dark
In this case, the shadowing is intentional. The function uses its own config. The global config is protected. This is a valid use of shadowing.
But if you meant to modify the global config, shadowing would be a bug. Always check your intent.
Shadowing and Variable Naming Rules
Good naming can prevent shadowing. Follow JavaScript Variable Naming Rules. Use descriptive names. Avoid single-letter names except in loops.
For example, use userName instead of name. This reduces the chance of conflict. It also makes your code self-documenting.
Shadowing in Different Contexts
Shadowing works in many contexts: functions, blocks, loops, and even classes. Each follows the same principle. The inner scope wins.
Shadowing in Nested Functions
// Nested functions
function outer() {
let message = "Hello";
function inner() {
let message = "Hi"; // Shadows outer message
console.log(message); // Output: Hi
}
inner();
console.log(message); // Output: Hello
}
outer();
Shadowing in Blocks
// Block shadowing
let value = 1;
{
let value = 2;
console.log(value); // Output: 2
}
console.log(value); // Output: 1
Conclusion
Variable shadowing is a fundamental JavaScript concept. It occurs when an inner variable hides an outer one. Understanding it helps you debug and write better code.
Use let and const for block scoping. Avoid unnecessary shadowing. Name your variables clearly. Check the JavaScript Variables Guide for more tips.
Now you know how shadowing works. Practice with examples. Soon, it will become second nature. Happy coding!