How does variable scope work?
By FrontendPro Editorial Team Updated 9/26/2026
Answer
Scope is the region of code where a name is visible. JavaScript has three levels, and which one a variable gets depends on how you declared it.
Global — declared outside any function or block. Visible everywhere, and in a browser var at the top level also attaches to window.
Function — var is scoped to the whole enclosing function, regardless of blocks.
Block — let and const are confined to the nearest { }, including if, for and bare blocks.
function demo() {
var functionScoped = "var";
if (true) {
var stillVisible = "var leaks out of the block";
let blockScoped = "let stays in";
}
console.log(stillVisible); // works
console.log(blockScoped); // ReferenceError
}
Why the difference matters
The classic bug is a loop with var, where every callback shares one binding:
for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)); // 3, 3, 3
for (let i = 0; i < 3; i++) setTimeout(() => console.log(i)); // 0, 1, 2
let creates a fresh binding each iteration, which is almost always what you meant.
Lookup goes outward only
When a name is not found, the engine checks the enclosing scope, then the one outside that, up to global — the scope chain. Inner scopes see outer variables; outer scopes never see inner ones. A name declared in an inner scope shadows the outer one of the same name for that region.
In practice
Default to const, use let when you must reassign, and avoid var entirely — its function scoping and hoisting to undefined cause bugs that block scoping simply prevents. Declaring variables in the smallest scope that works also keeps the code easier to follow.
