Hoisting is one of those JavaScript concepts that can cause surprising behavior if you’re not aware of how it works. Yet, once you understand it, you’ll write more predictable and bug-free code. In this blog post, we’ll demystify what hoisting is, how it affects variables and functions, and the differences between var, let, const, and function expressions.
Hoisting is JavaScript’s behavior of moving declarations to the top of their scope before code is executed.
For example:
console.log(x); // undefinedvar x = 10;
Behind the scenes, JavaScript interprets this as:
var x;console.log(x); // undefinedx = 10;
Only the declaration is hoisted, not the initialization.
var vs let / constvar — Hoisted and Initialized as undefinedconsole.log(a); // undefinedvar a = 5;
var variables are hoisted to the top of their function scope and initialized to undefined.
let / const — Hoisted but in the Temporal Dead Zone (TDZ)console.log(b); // ❌ ReferenceErrorlet b = 10;
console.log(c); // ❌ ReferenceErrorconst c = 20;
Although let and const are hoisted, they are not initialized. Accessing them before declaration results in a ReferenceError due to the temporal dead zone (TDZ).
sayHello(); // "Hello"function sayHello() {console.log("Hello");}
Function declarations are hoisted with their definitions, so you can safely call them before they appear in your code.
greet(); // ❌ TypeError: greet is not a functionvar greet = function () {console.log("Hi");};
Here, only the var greet declaration is hoisted and initialized as undefined. Trying to call greet() before the assignment causes a TypeError.
shout(); // ❌ TypeErrorconst shout = () => console.log("Shout!");
With const and arrow functions, the variable is hoisted but uninitialized (TDZ), so accessing it early throws a ReferenceError.
| Declaration Type | Hoisted? | Initialized? | Usable Before Declaration? |
|---|---|---|---|
var | ✅ Yes | ✅ As undefined | ⚠️ Yes, but risky |
let / const | ✅ Yes | ❌ No (TDZ) | ❌ No |
| Function Declaration | ✅ Yes | ✅ Yes | ✅ Yes |
| Function Expression | ✅ (var) | ❌ No | ❌ No |
| Arrow Function | ✅ (var) | ❌ No | ❌ No |
let and const over var to avoid unexpected hoisting behavior.const by default, and let when reassignment is necessary.Hoisting is a foundational concept in JavaScript that influences how your code is parsed and executed. Understanding how variable and function declarations are treated helps you write cleaner, more reliable code. By steering clear of var and being mindful of declaration order, you can avoid many common JavaScript pitfalls.
Stay tuned for our next post, where we’ll explore how closures interact with hoisting and function scopes!