5.2 — Hoisting, demystified
Lesson 1.4 called var "old and leaky" and promised the full story in Phase 5. This is that lesson. The word you'll hear in every interview is hoisting — and after 5.1 you already know the machinery behind it: pass 1 registers names before any line runs.
Today's whole lesson is one table: the three declaration kinds get three different registrations. var → name + undefined (reads early, silently wrong). let/const → name registered but untouchable until their line (the temporal dead zone — reads throw, loudly).
Function declarations → registered complete. Learn the table and every hoisting puzzle ever written becomes arithmetic.
console.log(a); var a = 1; console.log(b); let b = 2;
Pass 1 sweeps this code and registers both names — but look at the registry: a (var) holds the placeholder undefined, while b (let) is marked UNINITIALIZED. Both names exist before any line runs. What differs is what touching them early DOES.
The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”
The full table, worth memorizing: function f() {} → registered complete. var x → registered as undefined. let/const → registered uninitialized (TDZ; reads throw ReferenceError).
And var has a second leak this table explains: it ignores block scope. A var inside an if registers on the whole function's context — escaping the braces that 3.5 said contain things.
Why does var still exist? Compatibility — the web never breaks old pages. Your rule stands exactly as 1.4 stated it: const by default, let when reassigning, var only when reading old code. Now you can also explain the rule, which is what interviews actually test.
💼 On the job — interviewers phrase this a dozen ways — "is let hoisted?" is the trap. The precise answer: yes, all declarations are registered in pass 1 — but let/const are registered uninitialized, so unlike var they throw instead of reading undefined. That sentence separates memorizers from understanders.
⌨️ early birds and patient variables
Demonstrate mastery of both hoisting behaviors in one small program: a function declaration you deliberately call early, and a function expression you correctly call only after its line.
requirements:
- Very first line: call
stretch()— its function DECLARATION lives at the bottom of the file and returns"10 min". Print the returned value. - Then define
wakeas aconstARROW function returning"6am", and printwake()— called after its line, as expressions require.
when you press RUN, the console must show exactly:
✏️ Quick check 1
Type exactly what this prints:
console.log(x); var x = 3;
✏️ Quick check 2
This code throws. Type the ERROR NAME (the part before the colon):
console.log(y); let y = 3;
✏️ Quick check 3
Which kind can be safely CALLED above its line — a function declaration or a function expression? Type one word: declaration or expression.
🗣️ Now teach it back
The interview classic: “Is let hoisted?” Give the precise answer — covering what pass 1 does to var, let/const, and function declarations, and what the temporal dead zone actually is.
Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.