Hoisting in JavaScript
Definition: Hoisting is JavaScript’s default behavior of moving declarations (not initializations) to the top of their scope — either the global scope or the function scope. This allows variables and functions to be used before they are formally declared in the code.
In simple terms, during the compilation phase, JavaScript scans your code for variable and function declarations and “hoists” them to the top of their respective scopes before executing the code line by line.
How Hoisting Works Internally
When the JavaScript engine runs your code, it goes through two main phases:
- Memory Creation Phase: The engine reserves memory for variables and functions. Function declarations are fully stored in memory, while variables declared with
varare set toundefined. - Execution Phase: The code is executed line by line, replacing variables’ values as the code runs.
Example 1: Function Hoisting
Function declarations are hoisted completely. You can safely call a function before it’s defined.
|
1 2 3 4 5 6 7 |
sayHello(); // ✅ Works - Output: "Hello there!" function sayHello() { console.log("Hello there!"); } |
However, this only works for function declarations — not for function expressions or arrow functions.
Example 2: Variable Hoisting with var
Variables declared with var are hoisted but initialized as undefined. This is why you can access them before declaration without getting a ReferenceError — but the value will be undefined.
|
1 2 3 4 5 |
console.log(a); // Output: undefined var a = 10; console.log(a); // Output: 10 |
Behind the scenes, JavaScript treats it like this:
|
1 2 3 4 5 6 |
// Internally: var a; // Declaration hoisted console.log(a); // undefined a = 10; // Initialization stays in place |
Example 3: let and const Are Not Hoisted the Same Way
Variables declared with let or const are hoisted too, but they stay in a special state called the Temporal Dead Zone (TDZ) until the line where they’re initialized. Accessing them before initialization results in a ReferenceError.
|
1 2 3 4 5 6 7 |
console.log(b); // ❌ ReferenceError let b = 5; console.log(c); // ❌ ReferenceError const c = 15; |
Example 4: Function Expression vs Function Declaration
Only function declarations are hoisted — not function expressions or arrow functions.
|
1 2 3 4 5 6 7 |
greet(); // ❌ TypeError: greet is not a function var greet = function() { console.log("Hello!"); }; |
Here, the variable greet is hoisted (set to undefined), but its assigned function value is not. When the code executes, you’re trying to call undefined(), which throws an error.
Key Takeaways
- Only declarations (not initializations) are hoisted.
vardeclarations are hoisted and initialized withundefined.letandconstare hoisted but remain in the Temporal Dead Zone until initialized.- Function declarations are fully hoisted, but function expressions and arrow functions are not.
Best Practices
- Always declare variables and functions before using them to make code more readable and predictable.
- Prefer
letandconstinstead ofvarto avoid confusion caused by hoisting. - Use function declarations for global or reusable functions, and arrow functions for callbacks and inline use.
In short: Hoisting helps JavaScript interpret your code flexibly, but it can also cause confusing bugs. Understanding how it works is key to writing clean, predictable code.