Definition:
- A block is code inside
{ }(like in loops, if-statements, functions, etc.). - A variable is block-scoped if it can only be accessed inside that block.
Key Points:
- Variables declared with
letandconstare block-scoped. - Variables declared with
varare NOT block-scoped — they are function-scoped or globally scoped.
Example:
{
let a = 10;
const b = 20;
var c = 30;
}
console.log(typeof a); // undefined (block scoped)
console.log(typeof b); // undefined (block scoped)
console.log(c); // 30 (var is not block scoped)Definition: Shadowing happens when a variable in an inner scope has the same name as a variable in an outer scope, effectively overriding it within that inner scope.
Example:
let x = 10;
{
let x = 20; // shadows outer 'x'
console.log(x); // 20 (inner)
}
console.log(x); // 10 (outer)Happens when using let to shadow let or var to shadow var, or let to shadow var in different scopes.
var y = 5;
{
let y = 15; // ✅ legal shadowing
console.log(y); // 15
}
console.log(y); // 5Happens when using var to shadow a let or const in the same scope chain.
let z = 100;
{
// var z = 200; // ❌ SyntaxError: Identifier 'z' has already been declared
}Why?
Because var is function-scoped and would try to declare z in the same scope as the outer let, causing a conflict.
When a block executes:
- A new Lexical Environment is created for that block.
- Variables inside it live in that block's Variable Environment.
- If a variable has the same name as in the outer scope → shadowing happens.
"Block scope means variables declared with let and const are only accessible within the enclosing {}. Shadowing occurs when a variable in an inner scope has the same name as one in an outer scope, temporarily overriding it inside that scope. Legal shadowing is allowed when the scopes are separate, but shadowing a let/const with var in the same scope chain is illegal because var is function-scoped."