DEV Community

Cover image for JavaScript Hoisting + Temporal Dead Zone made easy
Sumit Saha
Sumit Saha

Posted on

JavaScript Hoisting + Temporal Dead Zone made easy

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';
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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:

Table representing Hoisting rules

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';
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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!');
}
Enter fullscreen mode Exit fullscreen mode

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!');
};
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
dotallio profile image
Dotallio

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?

Collapse
 
sumitsaha profile image
Sumit Saha

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.

Collapse
 
ghost_engineer_2883a1ca0a profile image
Info Comment hidden by post author - thread only accessible via permalink
Ghost Engineer

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

Collapse
 
sakawatullah profile image
Sakawat Ullah

👍

Collapse
 
sumitsaha profile image
Sumit Saha

Thanks for reading

Some comments have been hidden by the post's author - find out more