let is hoisted. But not the way most people think.
Here's what actually happens under the hood.
The Question
A junior asked me: "If let isn't hoisted, why do I get 'Cannot access before initialization' instead of 'not defined'?"
Fair question. The error message itself is a clue.
I knew let was hoisted. But I didn't actually know how it worked under the hood until I dug into the spec.
What Actually Happens
JavaScript runs in two phases:
Creation phase: Scans your code. Registers all identifiers in their respective lexical environments. This is hoisting.
Execution phase: Runs code line by line.
Both var and let get hoisted. Both get registered in scope. The difference is initialization.
The Key Difference
var gets initialized to undefined immediately during hoisting. You can access it anywhere, you just get undefined if you use it before assignment.
let gets registered but stays uninitialized. The engine knows it exists, but won't let you touch it until the declaration line. Try to access it? ReferenceError.
This is the Temporal Dead Zone.
Why It Matters
With var, you can accidentally use a variable before it's declared. You get undefined. The bug might not show up until later, somewhere else in your code.
With let, you crash immediately at the exact line where you made the mistake. Clear error. Easy fix.
The Proof
Try declaring let x inside a function where an outer x exists. Access it before the declaration.
You'll get an error about the inner x, proving it was already hoisted and is shadowing the outer one. It's just stuck in the TDZ.
If let wasn't hoisted, you'd access the outer variable instead.
Bottom Line
let is hoisted. Its binding exists from the start of the scope. It's just locked until initialization.
One small design choice that catches bugs early instead of letting them hide.
How many of you thought let wasn't hoisted at all?
#JavaScript #WebDevelopment #Programming #NodeJS #SoftwareEngineering
Great breakdown