JavaScript Hoisting

Hoisting is JavaScript's default behavior of moving declarations to the top of their scope before code execution. Understanding hoisting explains why you can use some variables and functions before they're declared in code, and why others throw errors.

Hoisting Behavior

Variable declarations (var, let, const) are hoisted to the top of their scope during the compilation phase, before code execution. This means JavaScript "knows about" these variables throughout their entire scope, even before the line where they're declared. However, the hoisting behavior differs significantly between var and let/const.

While declarations are hoisted, variable initializations (assignments) are NOT hoisted. The declaration moves to the top, but the assignment stays where you wrote it. With var x = 5, only "var x" is hoisted; the "= 5" part stays in place. This is why accessing a var variable before its assignment gives undefined, not 5.

Function declarations are fully hoisted—both the declaration and the function body move to the top. This lets you call functions before they appear in the code: greet() works even if function greet() is defined later. This is one of JavaScript's most convenient features, making code organization more flexible.

Variables declared with let and const are hoisted but placed in a "temporal dead zone" from the start of the block until the declaration line. Accessing them before declaration throws a ReferenceError, not undefined. They exist but are uninitialized. This prevents the confusing behavior of var where variables are usable before declaration.

Variables declared with var are hoisted and automatically initialized to undefined at the top of their scope. This is why console.log(x) before var x = 5 prints undefined rather than throwing an error—x exists and has the value undefined until the assignment executes. This behavior can be confusing and is why let/const are preferred.

// var hoisting
console.log(x); // undefined (not error!)
var x = 5;
console.log(x); // 5

// Same as:
// var x;
// console.log(x);
// x = 5;

// let/const hoisting - Temporal Dead Zone
// console.log(y); // Error!
let y = 10;

// Function hoisting
greet(); // Works!

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

// Function expression NOT hoisted
// sayHi(); // Error!
const sayHi = function() {
  console.log("Hi!");
};