JavaScript Hoisting
Understanding how JavaScript moves declarations
⬆️ What is Hoisting?
Hoisting is JavaScript's behavior of moving variable and function declarations to the top of their scope during compilation. It's like JavaScript "lifts" declarations up!
// This works because of hoisting!
console.log(myVar); // undefined (not an error!)
var myVar = "Hello World";
// JavaScript sees it like this:
// var myVar; // Declaration hoisted
// console.log(myVar); // undefined
// myVar = "Hello World"; // Assignment stays here
What Gets Hoisted?
var Variables
Hoisted and initialized with undefined
console.log(x); // undefined
var x = 5;
let & const
Hoisted but not initialized (Temporal Dead Zone)
console.log(y); // Error!
let y = 10;
Function Declarations
Fully hoisted - can be called before declaration
sayHello(); // Works!
function sayHello() {
console.log("Hello!");
}
Function Expressions
Not hoisted - treated like variables
sayBye(); // Error!
var sayBye = function() {
console.log("Bye!");
};
🔹 var Hoisting Example
var declarations are hoisted and initialized with undefined:
// What you write:
console.log("Before declaration:", myName); // undefined
var myName = "Alice";
console.log("After declaration:", myName); // "Alice"
// How JavaScript interprets it:
// var myName; // Hoisted to top, initialized with undefined
// console.log("Before declaration:", myName); // undefined
// myName = "Alice"; // Assignment happens here
// console.log("After declaration:", myName); // "Alice"
Output:
Before declaration: undefined
After declaration: Alice
🔹 let and const Hoisting
let and const are hoisted but not initialized (Temporal Dead Zone):
// This will cause an error
console.log(myLet); // ReferenceError: Cannot access before initialization
console.log(myConst); // ReferenceError: Cannot access before initialization
let myLet = "I'm let";
const myConst = "I'm const";
console.log(myLet); // "I'm let"
console.log(myConst); // "I'm const"
Output:
ReferenceError: Cannot access 'myLet' before initialization
🔹 Function Hoisting
Function declarations are fully hoisted:
// This works! Function is hoisted
console.log(add(5, 3)); // 8
function add(a, b) {
return a + b;
}
// But function expressions are not fully hoisted
console.log(multiply(4, 2)); // TypeError: multiply is not a function
var multiply = function(a, b) {
return a * b;
};
console.log(multiply(4, 2)); // 8 (now it works)
Output:
8
TypeError: multiply is not a function
8
🔹 Practical Hoisting Example
Understanding hoisting helps avoid common mistakes:
// Example showing hoisting behavior
function demonstrateHoisting() {
console.log("1. myVar:", myVar); // undefined (hoisted)
console.log("2. myFunc:", myFunc); // function (hoisted)
// This would cause an error:
// console.log("3. myLet:", myLet); // ReferenceError
var myVar = "I'm a var";
let myLet = "I'm a let";
function myFunc() {
return "I'm a function declaration";
}
console.log("4. myVar:", myVar); // "I'm a var"
console.log("5. myLet:", myLet); // "I'm a let"
console.log("6. myFunc():", myFunc()); // "I'm a function declaration"
}
demonstrateHoisting();
Output:
1. myVar: undefined
2. myFunc: function myFunc() { return "I'm a function declaration"; }
4. myVar: I'm a var
5. myLet: I'm a let
6. myFunc(): I'm a function declaration
🔹 Best Practices
To avoid hoisting confusion:
- Declare variables at the top of their scope
- Use let and const instead of var when possible
- Define functions before using them
- Use function expressions for conditional function creation
// Good practice
function goodExample() {
// Declare variables at the top
let name = "John";
let age = 25;
const PI = 3.14159;
// Define functions before using
function calculateArea(radius) {
return PI * radius * radius;
}
// Use them
console.log(`${name} is ${age} years old`);
console.log(`Circle area: ${calculateArea(5)}`);
}