Limit a temporary value to a block
Use a short-lived name inside a nested block without changing the outer binding.
JS Puzzles · Const
Variable shadowing happens when a nested scope declares a name already used outside it. With const, the inner binding takes precedence throughout the block and is inaccessible before initialization.
A block-scoped const declaration can reuse an identifier from an outer scope. Inside the block, name lookup selects the inner binding throughout that block, including before its declaration is executed; accessing it then throws a ReferenceError because it is in the temporal dead zone.
const name = value;const x = 1;
{
try {
console.log(x);
} catch (error) {
console.log(error.name);
}
const x = 2;
console.log(x);
}The inner declaration shadows the outer name, but the name is inaccessible until its declaration is reached.
Use a short-lived name inside a nested block without changing the outer binding.
Keep an outer configuration or state value unchanged while computing a local replacement.
Avoid accidental mutation of an outer identifier by giving a nested operation its own binding.
Shadowing occurs when an inner scope declares a variable with the same name as one in an outer scope. JavaScript resolves the inner binding first, so references in that inner scope use the inner variable.
Follow-up: What happens before the inner const declaration? The binding already occupies the block, but remains uninitialized, so access throws a ReferenceError.
A const declaration is block-scoped, and its name is available only after execution reaches the declaration. Before that point it is in the temporal dead zone.
Follow-up: Why is the outer binding not used during that interval? The inner declaration reserves the name for the entire block, so lookup finds the uninitialized inner binding first.
JavaScript searches the innermost lexical environment first, then successively searches outer environments. Therefore, a same-named inner declaration hides the outer declaration within its block.
Follow-up: Can the outer value still be accessed through the same identifier inside the block? Not while the inner binding is in scope; use a different name or restructure the scopes.
constletblock scopeLexical Environmenttemporal dead zoneclosure