DEV Community

Cover image for Hoisting in JavaScript
Ananya Mohanta
Ananya Mohanta

Posted on • Edited on

Hoisting in JavaScript

Why JavaScript Doesn’t Execute Code Top-to-Bottom ?
When I started learning JavaScript, hoisting felt like a bug pretending to be a feature.

Why didn’t this throw an error?
Why does let behave differently? (We'll study this later in another blog)
And why do functions work even before they’re defined?

The answer to all of this lives in Execution Context.

Once I understood how JavaScript prepares code before running it, hoisting stopped being confusing and started making sense.

Let's break it down.
Hoisting happens in the creation phase, not during the execution.

What is Hoisting?

Hoisting is JavaScript’s behavior of moving declarations to the top of their scope during the creation phase.

Not physically moving code — but allocating memory before execution starts.
Let's understand hoisting for var and functions with an example:

At first glance, this code looks wrong.

  • We are calling printMessage() before defining it.
  • We are logging x before assigning it.
  • We are even logging the function itself. Yet… this code works.

Why and How?

Now let's start with var.

What You Expect

Error, because x is declared later.

What Actually Happens

JavaScript stores the variable with a special keyword undefined.

Why?

During the creation phase, JavaScript does this:

Then during execution:

Key Rules for var

  • var is hoisted
  • Memory is allocated
  • Initialized with undefined
  • Scoped to function, not block

This is why var feels “weird” — but it’s actually consistent once you understand execution context.

Why Functions Are Fully Hoisted

This is where things get interesting.
During the creation phase:

  • JavaScript allocates memory
  • Stores the entire function definition So in memory:

JavaScript already knows what printMessage() is before execution begins. This is why function declarations are fully hoisted.

Now JavaScript starts executing the code from top to bottom.

Line 1

JavaScript finds the full printMessage() function in memory.
Output:

Line 2

JavaScript looks for x in memory.

  • x exists
  • Its value is undefined Output:  > Important > This is not an error because x was already created during the creation phase.

Line 3

Since printMessage points to the entire function, JavaScript prints the function itself.
Output:

Line 5

Now, during execution, x gets its actual value.
Memory update:

x → 10
Final Output

Now hoisting works little different for function expression.

TypeError: printMessage is not a function

Why?
Because only the variable is hoisted, not the function.
Creation phase:

This is why it throws an error.

For arrow functions it works in the same way how function expression behaves.
Finally, Hoisting is not magic.
It’s a side effect of how JavaScript creates execution contexts.
Once you understand:

  • Creation phase
  • Memory allocation
  • TDZ
  • Scope rules

Hoisting becomes predictable, logical, and honestly… kind of elegant.

If You like my content and want to connect with me, connect me on LinkedIn.

Top comments (0)