🧠 JavaScript Hoisting Explained Simply (With Examples)

Ujjwal KarUjjwal Kar
5 min read

Introduction to JavaScript Hoisting

JavaScript hoisting is a quirky concept that can easily trip up beginners. It's one of those behaviors in the language that you must see to believe. But once you understand what hoisting is and how it works under the hood, your JavaScript will instantly become more predictable and bug-free.


What Is Hoisting in JavaScript?

Hoisting is JavaScript’s default behavior of moving declarations to the top of their scope—before any code is executed. During the compilation phase, before your code actually runs, the JavaScript engine scans your code for declarations and places them in memory. But there’s a twist: not all declarations behave the same way.

What gets hoisted:

  • function declarations

  • var, let, and const variables (but differently)

What doesn't get hoisted:

  • Function expressions

  • Arrow functions

  • Class declarations


Function Declarations and Hoisting

✅ Fully Hoisted With Definitions

When you declare a function using the traditional function syntax, it's hoisted along with its body. That means you can call it before the line where it's written.

greet(); // ✅ Works

function greet() {
  console.log("Hello!");
}

You can safely call greet() before the function is defined in your code—JavaScript already knows what greet means during the compilation phase.


Hoisting with var

🤷 Declared, But Initialized as undefined

Variables declared with var are hoisted, but only the declaration—not the value assignment.

console.log(user); // undefined
var user = "Ujjwal";

Here, user exists in memory before the code runs, but it’s set to undefined until the assignment line is reached. This can lead to confusing bugs if you're unaware.


Hoisting with let and const

⚠️ Hoisted but Uninitialized – Welcome to the TDZ

Variables declared with let and const are also hoisted, but they’re not initialized. Trying to access them before the declaration causes a ReferenceError.

console.log(count); // ❌ ReferenceError
let count = 5;

This period—from the start of the scope to the line where the variable is declared—is called the Temporal Dead Zone (TDZ). It’s JavaScript’s way of saying: “You can’t use this yet.”


Visual Guide to JavaScript Hoisting

PhaseWhat Happens
CompilationAll declarations (var, let, const, function) are scanned and stored in memory
ExecutionCode is run line by line, and variable assignments take place

🔍 Tip: Visualizing this two-phase process makes hoisting much easier to understand.


Understanding Scope in JavaScript

DeclarationScope Type
varFunction Scope
let, constBlock Scope
functionFunction Scope

Scope defines where in your code a variable can be accessed. Hoisting respects these boundaries. So a let inside an if block stays inside that block—even if hoisted.


The Role of Execution Context

Behind the scenes, JavaScript builds an execution context for each function call or script. In the creation phase, it sets up memory space and hoists declarations. Understanding this memory model is key to mastering hoisting.


Common Pitfalls Due to Hoisting

  • Accessing a var variable too early results in undefined

  • Using let or const too early throws a ReferenceError

  • Overwriting functions declared later in code can lead to bugs


Best Practices to Avoid Hoisting Issues

  • Always declare variables and functions at the top of their scope

  • Use let and const instead of var for better safety

  • Never rely on hoisting for program logic


Comparison Table: var vs let vs const vs function

KeywordHoistedInitializedScope TypeNotes
functionFunctionCan be used before declaration
var✅ (as undefined)FunctionCan cause bugs if misused
let❌ (TDZ)BlockSafer than var
const❌ (TDZ)BlockMust be initialized

When to Use var, let, or const

  • Use const by default—it’s safe and immutable

  • Use let when you need to reassign

  • Avoid var unless you're dealing with legacy code


Real Examples of Hoisting in Action

function sayHi() {
  console.log(greeting); // undefined
  var greeting = "Hello";
}
sayHi();

In the example above, greeting is hoisted, but its assignment isn’t. So the console prints undefined.


Myths About JavaScript Hoisting

  • "let and const are not hoisted." → They are, just not initialized!

  • "Functions always hoist safely." → Only function declarations, not expressions.

  • "Hoisting is an error." → It's intentional behavior built into the language.


Advanced Concepts: Function Expressions and Arrow Functions

sayHi(); // ❌ TypeError
const sayHi = function() {
  console.log("Hi!");
};

This will throw an error. Why? Because sayHi is a const variable that’s hoisted but not initialized (TDZ again!).


Frequently Asked Questions (FAQs)

1. Is let hoisted in JavaScript?
Yes, but it’s not initialized until the line of declaration—this is why accessing it early throws a ReferenceError.

2. Why is var considered unsafe?
Because it's hoisted and initialized as undefined, it can cause unexpected bugs and confusing behavior.

3. Can I use a function before its declaration?
Only if it's declared with function, not with const or let function expressions.

4. What is the Temporal Dead Zone (TDZ)?
The TDZ is the period between entering scope and the actual line of declaration where let and const are inaccessible.

5. Does hoisting apply to classes in JavaScript?
Yes, classes are hoisted but not initialized—similar to let and const.

6. How can I visualize hoisting?
Think of JavaScript scanning your code first and putting all declarations in memory before it starts executing anything.


Conclusion and Final Thoughts

Hoisting is a fundamental part of JavaScript's execution model. Once you understand how declarations are hoisted during compilation, it becomes much easier to write clean, bug-free code. Stick to let and const, declare early, and keep an eye on scope. You'll find that hoisting is less of a mystery—and more of a superpower.

0
Subscribe to my newsletter

Read articles from Ujjwal Kar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ujjwal Kar
Ujjwal Kar

Associate Software Engineer with expertise in Full Stack Development and hands-on experience in executing Data Science projects. Seeking opportunities to apply and enhance knowledge in real-world problems.