Hoisting & the Temporal Dead Zone
Declarations are set up before any code runs — but let and const stay locked until their line executes.
Before running any code, JavaScript scans the current scope and sets up all declarations in advance — this is hoisting. `var` declarations are hoisted and initialized to `undefined`, so reading one early gives `undefined` rather than an error. `let` and `const` are hoisted too, but not initialized — they sit in the Temporal Dead Zone (TDZ) from the top of the scope until their declaration line runs, and touching them during that window throws a ReferenceError. Function declarations are hoisted with their entire body, so they're callable before their line.
Both a and b are hoisted, but only var is auto-initialized to undefined. let sits in the Temporal Dead Zone — reachable in scope, but forbidden to touch — until its own declaration line runs.