Yandex

JavaScript Hoisting
Variables, Functions, and Scope Mysteries Unraveled



Introduction to JavaScript Hoisting

Ever wondered why you can use a variable before it's defined in JavaScript? That's because of a concept called hoisting. At its core, hoisting is JavaScript's way of setting up memory before it starts running your code — quietly and invisibly behind the scenes.

What is Hoisting?

Hoisting is JavaScript’s default behavior of moving declarations to the top of the current scope (either function or global). But it doesn't move initializations.

It’s like the engine says, “Let me prepare all the variable and function names I’ll need before I begin.”

Variable Hoisting with var

Variables declared with var are hoisted — their declarations, not their initializations.


console.log(x);
var x = 5;
undefined

Why undefined and not a ReferenceError?

Behind the scenes, the JavaScript interpreter rewrites it like this:


var x;
console.log(x);
x = 5;

This means the var is hoisted, but its 5 isn't — hence undefined.

Variable Hoisting with let and const

Things get stricter with let and const. Yes, they are hoisted, but they live in the Temporal Dead Zone (TDZ) from the start of the block until the declaration is encountered.


console.log(y);
let y = 10;
ReferenceError: Cannot access 'y' before initialization

Here’s what you need to know:

  • let and const are hoisted.
  • But they are not initialized.
  • Accessing them before declaration throws an error.

Function Hoisting

Function declarations are fully hoisted — both their name and body.


greet();

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

JavaScript reads this as if the function was defined before the call. However, function expressions are a different story.

Function Expressions are NOT Hoisted (Well, Not Like You Think)


sayHi();

var sayHi = function() {
  console.log("Hi!");
}
TypeError: sayHi is not a function

What happened here? sayHi is hoisted as a var — which means it’s set to undefined — not as a function. So calling it throws an error.

Hoisting in Functions and Block Scope

Let's peek into a function to see hoisting at work:


function test() {
  console.log(a);
  var a = 20;
}
test();
undefined

Why? Because var a is hoisted to the top of the function scope, just like this:


function test() {
  var a;
  console.log(a);
  a = 20;
}

Block Scope and Hoisting

What happens inside a block?


{
  console.log(msg);
  let msg = "Block scope hoisting!";
}
ReferenceError: Cannot access 'msg' before initialization

Even though let msg is hoisted to the top of the block, it’s still uninitialized — welcome to the TDZ.

Hoisting Order: A Summary

Type Hoisted? Initialized? Accessible Before Declaration?
varYesYes (to undefined)Yes
letYesNoNo (TDZ error)
constYesNoNo (TDZ error)
Function DeclarationYesYesYes
Function ExpressionOnly variable nameNoNo (TypeError)

Best Practices to Avoid Hoisting Confusion

  • Always declare variables at the top of their scope.
  • Use let and const to prevent silent hoisting bugs.
  • Declare functions before you call them — even though declarations are hoisted, it improves readability.

Conclusion

Hoisting is one of those quirks that give JavaScript its charm — and sometimes, its confusion. But once you understand the rules, especially the differences between var, let, const, and functions, you’ll be well-equipped to write cleaner, more predictable code.

Remember, JavaScript is not reading your code top-down as you wrote it — it’s reordering it in memory before it runs. Once you embrace that mindset, hoisting becomes less magical and more logical.



Welcome to ProgramGuru

Sign up to start your journey with us

Support ProgramGuru.org

You can support this website with a contribution of your choice.

When making a contribution, mention your name, and programguru.org in the message. Your name shall be displayed in the sponsors list.

PayPal

UPI

PhonePe QR

MALLIKARJUNA M