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`.
A block is defined by a pair of curly braces {} (such as inside if statements, for loops, or standalone blocks).
let and const are block-scoped. Unlike legacy var (which leaks outside blocks), let and const variables die when their enclosing block finishes executing.
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)
}
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)
}
let variable inside a block with the same name as an outer variable shadows (overrides) the outer variable inside that block.var in For Loops: Using var i = 0 in loops creates a single global/function loop variable shared across async iterations. Use let i = 0 so each loop iteration gets its own fresh block variable!Write it yourself. The tests below run against your code.
Always use let and const to benefit from block scoping and TDZ safety. Next, let's learn JavaScript's superpower: Closures!
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.
`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.
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.