You write JavaScript. You log
a variable... and boom – "undefined" or even a scary "ReferenceError"! What just happened?!
Let's finally understand what's going on – once and for all – with a real story!! In this article, I'm going to explain what Hoisting really is and break down the mysterious concept of the Temporal Dead Zone in a way that actually makes sense. After reading this, if anyone asks you about these in a job interview - you'll have the perfect answer, no more confusion.
If you prefer watching over reading, I've also created a video tutorial with animated explanations and a live coding demo. Feel free to check it out below before diving into the details:
If you prefer reading over watching video, let's continue.
Meet Sam. Every morning, Sam goes to a coffee shop.
One day, before the waiter even arrives, Sam shouts: "I'll have my regular coffee!"
The waiter is confused. "Uh… we haven't even given you the menu yet, sir!"
Turns out, they changed the menu yesterday — no more regular coffee!
This is exactly what happens when you try to use a variable before declaring it. You're shouting at JavaScript: "Give me the value!"
But JS says: "Hold on — I haven't seen that variable yet!"
Now let's reveal the real twist: JavaScript does know that the variable exists! It just hasn't given it a value yet.
Why?
Because of something called: "Hoisting."
Hoisting means "lifting or moving something above."
JavaScript moves all declarations — not values — to the top of the scope.
Hoisting in Global Scope
Let's first understand the difference between Declaration and Initialization.
Declaration is when you tell JavaScript that a variable exists.
Initialization is when you assign a value to it.
console.log(coffee); // 👉 undefined
var coffee = 'Latte';
Check the example above. Here, we have declared a variable called coffee
and assigned its value to 'Latte'.
So var coffee
— is the declaration, and coffee = 'Latte'
is the initialization.
When we run this code, we see undefined
— not an error!
Because behind the scenes, JavaScript rewrote the code like this:
var coffee;
console.log(coffee); // still undefined
coffee = 'Latte';
So var
is hoisted and initialized as undefined
.
Only the declaration part (var x
) is lifted or hoisted to the top of the scope.
This is called "Hoisting"! It only affects declarations — initializations stay where they are.
That's why coffee = 'Latte'
— this remains in the same place or line.
👉 This is the first rule you have to remember.
We saw the use case with var
.
What about let?
Now we will see how let
and const
behave. See this example:
console.log(tea); // ❌ ReferenceError!
let tea = 'Green Tea';
Here, we tried to log the value of tea
before it was declared and initialized — but this time, we get a ReferenceError
!
That means JavaScript has no reference to the tea
variable at that point.
Surprising, right?
It shows that let
behaves differently from var
!
Let's take a closer look to understand what's really going on.
Because variables declared with let
and const
are also hoisted — but they are kept in something called the "Temporal Dead Zone" or TDZ
.
What does that mean?
Well, TDZ
is the time between when the scope starts and when the variable is declared.
// → scope starts here
console.log(tea); // ❌ ReferenceError!
// ↓ variable is declared here
let tea = 'Green Tea';
During this time, the tea variable is in the Temporal Dead Zone,
which means — in this period — the variable exists, but you're not allowed to touch it!
Think of it like this:
You're at an event.
There's a gift with your name on it.
But the host says: "Don't touch it until I officially hand it to you."
If you touch it too early — boom!!! — ReferenceError!!
Let's summarize this in one simple table:
So yes — hoisting happens for all.
But only var
is accessible before the line where it's declared — not let
and const
.
👉 This is the second rule you need to remember.
Hoisting in Block Scope
So far, we have seen hoisting in Global Scope. Now let's check what happens inside Block Scope.
Check the code example shown below:
{
console.log(msg); // ❌ ReferenceError
let msg = 'Hello';
}
Here, the rule is also the same.
Block-scoped variables like let and const hoist within that block only — will not go out of the block — and are still in the "Temporal Dead Zone".
{
console.log(num); // ✅ undefined
var num = 10;
}
And var
is function-scoped, not block-scoped.
So it still works — badly — even inside a block.
Simple!
Now see what happens for functions:
greet(); // ✅ Works
function greet() {
console.log('Good morning!');
}
Function declarations are fully hoisted — including the body.
So you can call greet()
before it's declared, and it works fine.
sayBye(); // ❌ TypeError
const sayBye = function() {
console.log('Bye!');
};
But this doesn't work. Because sayBye
is a const
.
So it follows the "Temporal Dead Zone" rule — not the function rule.
Same rule applies to the arrow functions as well!
So: Function declarations and function expressions work differently!
Here are my tips or best practices to avoid hoisting confusion:
✅ Always declare variables at the top of their scope
✅ Use let
and const
— avoid var
✅ Don't rely on hoisting — it's a behavior, not a feature
✅ Structure your functions to read top-down
✅ Use linters like ESLint — they can catch "Temporal Dead Zone" bugs
Here's the mindset tip I promised:
Think of Hoisting as JavaScript's pre-processing stage.
It scans your code before running it — pulling up declarations, but not their values.
So next time your code acts weird — don't panic.
✅ Check for Hoisting
✅ Check for Temporal Dead Zone
And write your code like you respect the timeline.
Thanks for reading this complete guide to JavaScript Hoisting!
If this helped you:
👍 Like the article
💬 Comment: "Hoisting makes sense now!"
🔔 Follow me for more clear JS lessons
Keep learning, and keep building. See you next time!
Top comments (5)
Love how you made hoisting actually click instead of just memorizing rules. Have you ever seen a wild bug in the real world where hoisting totally messed up someone’s code?
Thanks for reading through everything and noticing my explanation. Yeah, I've seen a lot of people mess things up, especially when they use "var" and mix it with the global context.
try this if you get stuck during the interview. its an AI co-pilot that solves the questions for you so you can focus on the more important part of the interview, the communication part. its also a really good study tool: ghostengineer.com
👍
Thanks for reading
Some comments have been hidden by the post's author - find out more