Prompt
Write hoistingDemo() demonstrating hoisting: call a function BEFORE its declaration
(works — declarations hoist entirely) and read a var BEFORE its assignment (yields undefined).
Return { fnResult, varBeforeInit, myVar } where varBeforeInit is String(myVar) captured
before the assignment (so it's the string 'undefined').
Solution
Hoisting isn't a quirk — it's the visible evidence that JavaScript executes in two phases. When a function is called, the engine first creates the execution context: it scans the body, registers every var in the environment record initialized to undefined, and registers every function declaration fully, body and all. Only then does execution begin, line by line. Nothing "moves to the top"; the names simply already exist before the first line runs.
That model explains both behaviors here in one breath. hoistedFunction() works before its declaration because the whole function object was created during the setup phase. myVar reads as undefined — not a ReferenceError — because its declaration was registered but its assignment is an ordinary runtime statement that hasn't executed yet. Declaration and initialization are two different events; hoisting affects only the first.
Complete the picture unprompted: let/const are also hoisted — their names are reserved during setup — but left uninitialized, so touching them before the declaration line throws. That window is the temporal dead zone, and it exists precisely to turn the silent-undefined bug you just demonstrated into a loud error. Function expressions (var f = function(){}) hoist like any var: name yes, function no.
Red flag: "let and const aren't hoisted." They are — TDZ is uninitialized hoisting, and stating it wrong tells the interviewer your model is memorized, not understood.
Say it: "The engine registers declarations in a setup phase before executing a single line — var initializes to undefined, function declarations hoist whole, and let/const hoist uninitialized, which is the TDZ."