Last modified: Jul 17, 2026

JavaScript Hoisting Explained Clearly

JavaScript hoisting is a core concept that often confuses beginners. It describes how variable and function declarations are moved to the top of their scope before code execution. This article explains hoisting with variables using clear examples and simple language.

Understanding hoisting helps you write predictable code. It also prevents common bugs. Let's explore how var, let, and const behave differently during hoisting.

What is Hoisting in JavaScript?

Hoisting is JavaScript's default behavior. It moves all declarations to the top of the current scope. This happens during the compilation phase, before the code runs.

Only the declarations are hoisted, not the initializations. This means you can use a variable before it is declared, but the value will be undefined until the assignment line is reached.

For example, consider this code:

// Example of hoisting with var
console.log(myName); // Output: undefined
var myName = "Alice";
console.log(myName); // Output: Alice

The first console.log does not throw an error. It prints undefined because the declaration var myName was hoisted to the top. The assignment myName = "Alice" stayed in place.

Hoisting with var

The var keyword is the classic example of hoisting. When you declare a variable with var, its declaration is hoisted to the top of its function or global scope. The variable is initialized with undefined.

This can lead to unexpected results. Many developers consider this a flaw. Modern JavaScript prefers let and const for more predictable behavior.

// Hoisting with var in a function
function testVar() {
  console.log(myVar); // Output: undefined
  var myVar = "Hello";
  console.log(myVar); // Output: Hello
}
testVar();

Internally, the JavaScript engine sees the code like this:

// How the engine interprets the above function
function testVar() {
  var myVar; // declaration hoisted
  console.log(myVar); // undefined
  myVar = "Hello"; // assignment stays here
  console.log(myVar); // Hello
}
testVar();

Notice that the declaration moves up, but the assignment remains at its original line. This is the core of hoisting behavior with var.

For more details on variable naming, check our JavaScript Variable Naming Rules guide.

Hoisting with let and const

Variables declared with let and const are also hoisted. However, they are not initialized. They enter a "temporal dead zone" from the start of the block until the declaration is encountered.

If you try to access them before the declaration, JavaScript throws a ReferenceError. This makes the code safer and prevents accidental use of uninitialized variables.

// Hoisting with let
console.log(myLet); // ReferenceError: Cannot access 'myLet' before initialization
let myLet = "World";
// Hoisting with const
console.log(myConst); // ReferenceError: Cannot access 'myConst' before initialization
const myConst = "Constant";

The temporal dead zone lasts from the block start until the declaration line. This encourages you to declare variables at the top of their scope for clarity.

To understand variable scopes better, read our JavaScript Variable Scope Explained article.

Function Hoisting

Function declarations are fully hoisted. This means you can call a function before its definition in the code. This is different from variable hoisting.

// Function declaration hoisting
greet(); // Output: Hello!

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

Function expressions, however, are not hoisted. If you assign a function to a variable using var, let, or const, only the variable declaration is hoisted (or not initialized), not the function assignment.

// Function expression hoisting with var
sayHi(); // TypeError: sayHi is not a function
var sayHi = function() {
  console.log("Hi!");
};
// Function expression with let
sayBye(); // ReferenceError: Cannot access 'sayBye' before initialization
let sayBye = function() {
  console.log("Bye!");
};

This distinction is important when organizing your code. Always prefer function declarations for hoisting benefits.

Practical Examples of Hoisting

Let's look at a more complex example to see how hoisting affects real code. Consider a loop using var.

// Hoisting in a loop with var
for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // Output: 3, 3, 3
  }, 100);
}

All three callbacks print 3 because i is hoisted to the function scope. By the time the callbacks run, the loop has finished and i is 3.

Using let fixes this. Each iteration gets its own block-scoped variable.

// Hoisting in a loop with let
for (let j = 0; j < 3; j++) {
  setTimeout(function() {
    console.log(j); // Output: 0, 1, 2
  }, 100);
}

This shows why let and const are preferred in modern JavaScript. They provide block scoping and avoid hoisting pitfalls.

For more examples, see our JavaScript Variables Examples page.

Best Practices to Handle Hoisting

To write clean and predictable code, follow these best practices:

  • Always declare variables at the top of their scope. This makes hoisting less surprising.
  • Use let and const instead of var. They have clearer scoping rules and temporal dead zones.
  • Avoid relying on hoisting for variable access. It can make code harder to read.
  • Use function declarations for functions you want to call before definition.
  • Use strict mode ("use strict") to catch hoisting-related errors early.
// Best practice example
"use strict";

function example() {
  let x = 10; // declared at top of block
  const y = 20; // declared at top of block
  console.log(x + y); // Output: 30
}
example();

Following these rules makes your code more maintainable and less error-prone.

Common Misconceptions About Hoisting

Many beginners think hoisting moves the entire variable declaration and assignment. This is false. Only the declaration moves.

Another misconception is that let and const are not hoisted. They are hoisted, but they are not initialized. The temporal dead zone prevents access until the declaration.

Understanding these nuances helps you debug issues faster. It also improves your overall JavaScript knowledge.

For a complete overview of variable types, visit our Types of JavaScript Variables guide.

Conclusion

JavaScript hoisting is an important mechanism. It moves variable and function declarations to the top of their scope. var declarations are hoisted and initialized with undefined. let and const are hoisted but remain uninitialized until the declaration line.

Using let and const is the modern standard. They avoid many hoisting pitfalls and make code more predictable. Always declare variables at the top of their scope for clarity.

Practice with examples to master hoisting. It will make you a better JavaScript developer and help you write cleaner code.