Understanding the Temporal Dead Zone and the Compile Phase.
Timothy was staring at his monitor, confused. He had written a function at the bottom of his file, called it at the top, and it worked. But when he tried to log a variable the same way, it crashed.
// This works?
sayHello();
// This crashes?
console.log(framework);
function sayHello() {
console.log("Hello!");
}
let framework = "React";
"It makes no sense," Timothy said. "Does JavaScript read from the top down or not?"
Margaret picked up a piece of chalk. "It does both," she said. "You are confusing the Execution Phase with the Compile Phase."
The Two Passes
Margaret drew a timeline on the board.
"The JavaScript Engine does not just run your code immediately," she explained. "It makes two passes over your file."
-
Pass 1: Compilation (The Creation Phase). The engine scans for declarations (
var,let,function,const). It allocates memory for them, but it does not assign values. - Pass 2: The Execution Phase. The engine runs the code line by line and assigns values.
"This split creates a phenomenon we call Hoisting," Margaret said. "But different types of variables behave differently during the first pass."
The Function Declaration
Margaret pointed to Timothy's working function.
function sayHello() { ... }
"Function Declarations are special," she said. "During the Compilation Phase, the engine hoists the entire function—the name and the body—into memory."
"So when the Execution Phase starts," Timothy realized, "the tool is already fully built."
"Exactly. You can call it before you define it."
The var Hoist (Function Scope)
Margaret wrote a var example on the board.
console.log(myVar); // undefined
var myVar = 10;
"When the engine sees var," she explained, "it allocates memory and initializes it with undefined immediately. Note that var is hoisted to the top of the Function Scope."
-
Compilation: "I see
myVar. I will save space and set it toundefined." -
Execution: The first line runs. It sees
undefined. The second line runs, andmyVarbecomes10.
"It fails silently," Margaret warned. "It runs, but the data is wrong."
The Temporal Dead Zone (Block Scope)
Then Margaret wrote the modern example using let and const.
{
console.log(myLet); // ReferenceError!
let myLet = 20;
}
"This is where let and const differ," she said. "They are Block Scoped (confined to the curly braces {}). They are technically hoisted—the engine knows they exist—but they are uninitialized."
She drew a shaded box on the timeline between the start of the block and the line where the variable is defined.
"This gap is called the Temporal Dead Zone (TDZ)."
"If you try to touch the variable while it is in the Dead Zone," Margaret said, "the engine throws a ReferenceError. It refuses to let you use a variable that hasn't been assigned yet."
The Trap: Function Expressions
Margaret wiped a section of the board. "Here is the trap that catches everyone in interviews. What happens if we use a Function Expression?"
She wrote two examples:
Example A: The const Crash
sayHi(); // ReferenceError! (TDZ)
const sayHi = function() { ... };
Example B: The var Crash
sayHello(); // TypeError: sayHello is not a function
var sayHello = function() { ... };
Timothy looked closely. "Wait. The var version didn't say 'ReferenceError'. It said 'Type Error'."
"Correct," Margaret said. "Because var was hoisted. The engine initialized sayHello as undefined."
"So when I tried to call sayHello()..."
"You were trying to call undefined as a function," Margaret finished. "That is a Type Error. The variable exists, but it is not a function yet."
The Cheat Sheet
Margaret drew a final grid on the board to summarize the rules.
| Type | Hoisted? | Initial Value | Scope |
| :--- | :--- | :--- | :--- |
| function | Yes | The Body | Block* |
| var | Yes | undefined | Function |
| let/const | Yes (TDZ) | <uninitialized> | Block |
* In Strict Mode/Modules
The Conclusion
Timothy looked at his code. He moved his function calls below his definitions.
"Hoisting isn't magic," he said. "It's just memory allocation."
"Correct," Margaret said. "The engine prepares the room before the party starts. If you try to eat the food before it's plated, you will crash."
Aaron Rose is a software engineer and technology writer at tech-reader.blog and the author of Think Like a Genius.
Top comments (3)
Really nice explanation 👍
The compile phase vs execution phase part makes hoisting much easier to understand.
A lot of people think JavaScript runs only top-to-bottom, but this shows why functions work before definition while let/const throw errors.
The Temporal Dead Zone example is especially helpful — that’s usually where beginners get confused.
Also the comparison between var → undefined and let/const → ReferenceError is very clear.
Honestly, once you understand that hoisting is just memory allocation first, execution later, most JS “weirdness” suddenly makes sense.
Great practical breakdown, not just theory 👌
thanks Bhavin🙏❤✨
Some comments may only be visible to logged-in visitors. Sign in to view all comments.