Block Scope {} & The Temporal Dead Zone (TDZ)
Quick Overview
`let` and `const` are hoisted like `var`, but stay unreachable until their declaration runs. Touching one in that gap throws a `ReferenceError` instead of quietly handing back `undefined`.
Deep Dive
1. Blocks & Scope Boundaries
A block is defined by a pair of curly braces {} (such as inside if statements, for loops, or standalone blocks).
2. Why It Matters
let and const are block-scoped. Unlike legacy var (which leaks outside blocks), let and const variables die when their enclosing block finishes executing.
3. What is the Temporal Dead Zone (TDZ)?
The TDZ is the time window between when a let or const variable enters scope (Phase 1 Memory Allocation) and when it is declared and assigned a value (Phase 2 Execution). Accessing a variable while it is in its TDZ throws an uncaught ReferenceError!
if (true) {
// === TDZ for 'score' starts here! ===
// console.log(score); // ReferenceError: Cannot access 'score' before initialization
let score = 95; // === TDZ ends here! ===
console.log(score); // 95 (Safe to access)
}
4. Block Scope vs. Function Scope
function testBlock() {
if (true) {
var varVariable = "I leak out!";
let letVariable = "I stay inside!";
}
console.log(varVariable); // "I leak out!" (var ignores block boundary!)
// console.log(letVariable); // ReferenceError! (let is block-scoped)
}
5. Common Mistakes
- Shadowing Outer Variables Unintentionally: Declaring a
letvariable inside a block with the same name as an outer variable shadows (overrides) the outer variable inside that block. - Using
varin For Loops: Usingvar i = 0in loops creates a single global/function loop variable shared across async iterations. Uselet i = 0so each loop iteration gets its own fresh block variable!
6. Try It Yourself
Write it yourself. The tests below run against your code.
Fix Temporal Dead Zone ReferenceError
Examples
7. Next Steps
Always use let and const to benefit from block scoping and TDZ safety. Next, let's learn JavaScript's superpower: Closures!
Next Up in JavaScript Engine & Core Language
Data Types in JavaScript: Primitives vs. Objects
Primitives copy by value and objects copy by reference, so `b = a` duplicates a number but shares an object. That single distinction explains most surprise mutations in a codebase.
Variables: const, let & var (The Box Metaphor)
`const` prevents reassignment, not mutation: a `const` object's properties can still be changed. `let` is scoped to its block, while `var` is function-scoped and leaks out of loops.
Strings & Template Literals `${}`
Only backticks interpolate: `${user}` reads the variable, while the identical text in quotes prints literally. Strings are immutable, so every method returns a new one rather than editing in place.