DEV Community

Cover image for Understanding Hoisting in JavaScript: A Simple Guide
Taskin Mohammad Mubassir
Taskin Mohammad Mubassir

Posted on

Understanding Hoisting in JavaScript: A Simple Guide

JavaScript Hoisting

๐Ÿ”น What is Hoisting?
Hoisting is JavaScript's default behavior of moving declarations of functions and variables to the top of their scope before the code is executed. This means you can use a function or variable before it has been physically declared in the code. However, it's important to understand that only the declarations are hoisted, not the initializations (the assignment of a value).

In simple terms:
JavaScript scans the entire code first, remembers all variable and function declarations, and then starts running the code.
Variable Hoisting
How hoisting works with variables depends on whether you use var, let, or const.

  1. Using var Variables declared with var are hoisted to the top of their scope and are initialized with a value of undefined. This means you can access the variable before its declaration without an error, but its value will be undefined until the assignment is made. Example: code:
console.log(myVar);         // Outputs: undefined 
var myVar = "Hello, World!"; 
console.log(myVar);         // Outputs: "Hello, World!"
Enter fullscreen mode Exit fullscreen mode

How JavaScript sees it:
Code

var myVar;      // Declaration is hoisted and                          initialized as undefined          
console.log(myVar); 
myVar = "Hello, World!";    // Initialization happens here 
console.log(myVar);
Enter fullscreen mode Exit fullscreen mode
  1. Using let and const Variables declared with let and const are also hoisted, but they are not initialized with a default value. Accessing a let or const variable before it is declared will result in a ReferenceError. This is due to the Temporal Dead Zone (TDZ), which is the time from the start of the block until the variable declaration is processed. Example: Code
console.log(myLet);             // Throws ReferenceError: Cannot access                       'myLet' before initialization 
let myLet = "This will not work";
Enter fullscreen mode Exit fullscreen mode

Function Hoisting

  1. Function Declarations Function declarations are fully hoisted, meaning both the function's name and its entire logic are moved to the top. This allows you to call a function before it is declared in your code. Example: code
sayHello();             // Outputs: "Hello there!" 
function sayHello() { 
  console.log("Hello there!"); 
}
Enter fullscreen mode Exit fullscreen mode
  1. Function Expressions Function expressions, where a function is assigned to a variable, are not hoisted in the same way. If the variable is declared with the var keyword, the declaration is hoisted and initialized to undefined. Trying to call it before the assignment will result in a TypeError. If declared with let or const, it will be subject to the Temporal Dead Zone and throw a ReferenceError. Example (with var): code
sayGoodbye();       // Throws TypeError: sayGoodbye is not a function 
var sayGoodbye = function() { 
  console.log("Goodbye!"); 
};

Enter fullscreen mode Exit fullscreen mode

๐Ÿ”น Example Code

console.log(a);
console.log(b);
console.log(c);

let a = 10;
const b = 20;
var c = 30;

hoistingFunction();
notHostingFunction();

function hoistingFunction() {
  console.log('hi');
}
const notHostingFunction = () => {
  console.log('hello');
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”น Step-by-Step Explanation
During the compilation phase, JavaScript hoists declarations:

var c;                 // Hoisted and initialized with undefined
let a;                 // Hoisted but NOT initialized (TDZ)
const b;               // Hoisted but NOT initialized (TDZ)
function hoistingFunction(){console.log('hi');} // Fully hoisted
const notHostingFunction;         // Declared but not initialized
Enter fullscreen mode Exit fullscreen mode

During execution, code runs line by line:
console.log(a) โ†’ โŒ Error: Cannot access 'a' before initialization
console.log(b) โ†’ Not reached (script already stopped)
console.log(c) โ†’ Not reached

  • Variables with let and const are in the Temporal Dead Zone (TDZ) until their declaration line is executed.
  • var is accessible before initialization but holds undefined.

๐Ÿ”น Function Hoisting
โœ… Function Declarations

sayHi();
function sayHi() {
  console.log('Hello');
}
Enter fullscreen mode Exit fullscreen mode

โœ… Works perfectly because function declarations are fully hoisted (both name and body).
โŒ Function Expressions / Arrow Functions

sayHello();  // Error
const sayHello = () => console.log('Hello');
Enter fullscreen mode Exit fullscreen mode

๐Ÿšซ Error: Cannot access 'sayHello' before initialization
Reason: Only the variable declaration (const sayHello) is hoisted, not the function value.

๐Ÿ”น Variable Hoisting Summary

๐Ÿ”น Temporal Dead Zone (TDZ)
The TDZ is the time between the start of the scope and the line where a let or const variable is declared.
Accessing these variables during the TDZ results in a ReferenceError.
Example:

console.log(x);  // โŒ ReferenceError
let x = 5;
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”น Corrected Version of the Example Code

let a = 10;
const b = 20;
var c = 30;

console.log(a); // 10
console.log(b); // 20
console.log(c); // 30

hoistingFunction(); // โœ… Prints 'hi'

function hoistingFunction() {
  console.log('hi');
}


notHostingFunction(); // โŒ ReferenceError (Cannot access 'ok' before                          initialization)
const notHostingFunction = () => {
  console.log('hello');
};

Enter fullscreen mode Exit fullscreen mode

๐Ÿ”น Key Takeaways

  • Only declarations are hoisted, not initializations.
  • var variables are hoisted and initialized with undefined.
  • let and const are hoisted but remain in the Temporal Dead Zone until their line of declaration.
  • Function declarations are fully hoisted (can be called before they appear).
  • Function expressions (arrow or anonymous) behave like variablesโ€”not callable before initialization.

Top comments (0)