Understand where variables live and where they can be accessed — the rules that govern visibility across global scope, function scope, and block scope.
Scope in JavaScript refers to the accessibility (visibility) of variables in different parts of the program. It determines where a variable can be read or modified.
There are three main types of scope in JavaScript: Global Scope
— accessible everywhere; Function Scope — accessible only
inside the function where it was declared; and Block Scope
— accessible only inside the {} block where it was declared
(applies to let and const).
Scope answers one question: "Where can I use this variable?"
{} — only accessible within that block (let / const)
let name = "Aman"; // global — declared outside everything
function showName() {
console.log(name); // accessible inside function
}
showName();
console.log(name); // accessible outside too
name is declared at the top level — it belongs to the global scopefunction test() {
let message = "Hello"; // function-scoped
console.log(message); // works fine inside
}
test();
// Trying to access outside the function:
try {
console.log(message); // ReferenceError
} catch (e) {
console.log("Error:", e.message);
}
message is created when test() runs and destroyed when it endsReferenceErrorif (true) {
let x = 10;
const y = 20;
console.log(x, y); // works inside the block
}
// Trying to access outside the block:
try {
console.log(x);
} catch (e) {
console.log("Error:", e.message);
}
try {
console.log(y);
} catch (e) {
console.log("Error:", e.message);
}
let and const are block-scoped — they only exist within the {} they were declared inif, for, while, or a standalone {}ReferenceErrorif (true) {
var a = 5; // var IGNORES block scope
let b = 10; // let respects block scope
}
console.log(a); // 5 — leaks out of the block!
try {
console.log(b); // ReferenceError
} catch (e) {
console.log("Error:", e.message);
}
var is function-scoped, not block-scoped — it leaks out of if, for, and while blocksvar is avoided in modern JavaScriptlet and const stay contained to their block — use them insteadThink of scope like rooms in a house — each has different levels of access:
Click ▶ Preview, then press the button to see global and local variables behave differently — the global is always reachable, the local disappears after the function ends.
<!DOCTYPE html>
<html>
<head><title>Scope Demo</title></head>
<body style="font-family:sans-serif;padding:24px;background:#f8f9fa">
<h2>Scope Demo</h2>
<button onclick="checkScope()"
style="padding:8px 20px;background:#f7df1e;border:none;
border-radius:6px;cursor:pointer;font-weight:700;font-size:1rem">
Check
</button>
<div id="output" style="margin-top:16px;line-height:2.2;font-size:0.95rem"></div>
<script>
let globalVar = "I am global"; // global scope
function checkScope() {
let localVar = "I am local"; // function scope
let html =
"<b>Inside function:</b><br>" +
"globalVar → " + globalVar + "<br>" +
"localVar → " + localVar + "<br><br>" +
"<b>Outside function:</b><br>" +
"globalVar → " + globalVar + "<br>" +
"localVar → <b style='color:red'>ReferenceError (not accessible)</b>";
document.getElementById("output").innerHTML = html;
}
</script>
</body>
</html>
let city = "Mumbai"; // global
function showCity() {
// your code here
}
showCity(), print the global variable citycity outside itfunction secretRoom() {
let secret = "hidden value";
console.log(secret); // works
}
secretRoom();
secretRoom(), try to console.log(secret) outside ittry/catch to see the ReferenceError messagelet with var — observe how the behaviour changeslet (and const) are block-scoped — they stay inside the {} they are declared in. var is function-scoped and leaks out of blocks like if and for.
function test() {
let x = 10;
}
test();
console.log(x);
x is declared with let inside test() — it is function-scoped and cannot be accessed outside. JavaScript throws a ReferenceError.
Keep variables as local as possible — declare them in the smallest scope where they are needed. This avoids accidental overwrites and makes code easier to reason about:
// ✗ Unnecessary global
let result;
function calculate() {
result = 5 + 3;
}
calculate();
console.log(result);
// ✓ Keep it local, return the value
function calculateClean() {
let result = 5 + 3;
return result;
}
console.log(calculateClean());
Variable shadowing — a local variable can have the same name as a global one. Inside the function, the local version takes priority:
let x = 10; // global x
function test() {
let x = 20; // local x — shadows the global
console.log(x); // 20 — sees the local one
}
test();
console.log(x); // 10 — global is unchanged
Never use var in modern JavaScript — its function-only scoping leaks variables out of loops and if blocks in ways that cause subtle bugs:
// var leaks — i survives after the loop
for (var i = 0; i < 3; i++) {}
console.log(i); // 3 — leaked!
// let is contained — i does not survive
for (let j = 0; j < 3; j++) {}
try {
console.log(j);
} catch (e) {
console.log("Error:", e.message); // ReferenceError
}
Proper scoping improves memory management — local variables are garbage-collected when their function ends, whereas globals persist for the entire lifetime of the page.
There are two variables named x — one global, one local. Which one
does each console.log see? Predict both outputs before running.
let x = 10;
function test() {
let x = 20;
console.log(x);
}
test();
console.log(x);
// Two variables — same name, different scopes:
// Global x = 10 (line 1)
// Local x = 20 (inside test())
// Step 1: test() is called
// JavaScript enters the function scope
// A new local x = 20 is created — it SHADOWS the global x
// console.log(x) inside sees the LOCAL x
// Output line 1 → 20
// Step 2: test() ends
// The local x is destroyed — it no longer exists
// We are back in the global scope
// Step 3: console.log(x) outside
// Only the global x = 10 is visible here
// Output line 2 → 10
// Final output:
// 20 ← local x inside test()
// 10 ← global x, unchanged
// Key takeaway:
// Shadowing lets inner scopes reuse a name without
// affecting the outer variable. The two x values
// are completely independent of each other.