Glossary / Block scope
Block scope
Block scope restricts a binding to a lexical block, commonly the braces of an if, loop, switch, or standalone block. let and const create block-scoped bindings; var does not. Block scope makes local lifetime visible in code and avoids many accidental leaks from conditional and loop declarations.
let, const, and var
if (ready) {
let message = "go";
const code = 200;
}
// message and code are not visible here
A const binding cannot be reassigned, but an object it references can still be mutated. Lexical declarations cannot be redeclared in the same scope and are subject to the temporal dead zone before initialization. var is function-scoped and hoisted with undefined, so a var declared inside an if or loop can be visible outside the braces.
let in a loop creates a fresh per-iteration binding for closures:
const callbacks = [];
for (let i = 0; i < 3; i++) callbacks.push(() => i);
callbacks.map((fn) => fn()); // [0, 1, 2]
This differs from the classic var loop capture, where each callback observes the same function-scoped binding after the loop ends. Use the narrowest useful scope, but avoid gratuitous blocks that make control flow harder to follow.
Interview questions
- Does
varrespect anifblock? No; it is scoped to the nearest function or script environment. - Does const make an object immutable? No; it prevents rebinding, not mutation of the referenced object.
- Why does
letwork for loop callbacks? Each iteration gets its own lexical binding. - What error may occur when a let binding is read too early? ReferenceError from its temporal dead zone.