Hoisting in JavaScript: Variable Hoisting and Function Hoisting

Hoisting in JavaScript: Variable Hoisting and Function Hoisting

06 Aug 2024
Beginner
311 Views
13 min read

JavaScript Hoisting

Hoisting in JavaScript is a feature that allows variables and functions to be used even before their declaration. This increases code flexibility and avoids "undefined" errors during program execution.

In this JavaScript tutorial, we'll discuss JavaScript hoisting, the types of JavaScript hoisting, i.e., variable and function hoisting, temporal dead zone, and more.

Read More: JavaScript Interview Questions and Answers (Fresher + Experience)

What is Hoisting in JavaScript?

Hoisting is JavaScript's default behavior of moving the declarations of variables and functions on top of their containing scope at the time of compilation so that they can be accessed in that entire scope regardless of their declaration place. The JavaScript interpreter splits the declaration and assignment of variables and functions before any code execution.

To understand JavaScript Hoisting, you must be very well aware of the below two topics:

  1. Variables in JavaScript: Declaration, Types, Scope
  2. Functions in JavaScript: User-Defined and Standard Library Functions

Types of Hoisting in JavaScript

There are two types of JavaScript Hoisting:

  1. Variable Hoisting
  2. Function Hoisting

We'll understand both these types in detail in the below section.

1. Variable Hoisting in JavaScript

In JavaScript, we declare variables with keywords like var, let, and const. Hence, the hoisting behavior depends on the keyword usage. There's also a case where no such keywords are used to declare variables. Let's take a look:

1. Variable Hoisting With 'var'

When you declare a variable in JavaScript using the var keyword, the interpreter hoists it with the default value of undefined.


// use the message variable before declaration
console.log(greet);

// variable declaration using var keyword
var greet;

var msg
console.log(msg);

In the above code, the first line console.log(greet) output is undefined because greet is hoisted and given a default value. The above two lines are equivalent to the next two lines, where the variable msg is declared first and then printed.

Output

undefined
undefined

Remember that printing an undeclared variable will throw a ReferenceError.

// use the message variable before declaration
console.log(greet);

Output

console.log(greet);
            ^
ReferenceError: greet is not defined

Similarly, using a variable before assigning it with a value will throw a ReferenceError because no declaration is hoisted.

console.log(greet);
greet = "Welcome to ScholarHat"

Output

console.log(greet);
            ^
ReferenceError: greet is not defined

2. Variable Hoisting With 'let' and 'const'

When we declare a variable with 'let' or 'const,' it is hoisted on top without initializing it with any default value like 'undefined.' It gives a ReferenceError when you access an undeclared let or const variable.


// use the message variable before declaration
console.log(message);

// variable declaration using let keyword
let message;

In the above code, the variable message is declared with let and so is not assigned any default value when hoisted.

Output

console.log(message);
            ^
ReferenceError: Cannot access 'message' before initialization

As the variable is hoisted, the error shown is "Cannot access 'message' before initialization." If it wasn't hoisted, the error would have been "ReferenceError: message is not defined." This indicates that the let or const variable is initialized somewhere.

Temporal Dead Zone

We saw above that accessing undeclared let or const variable gives a ReferenceError. This is because of the temporal dead zone (TDZ). The temporal dead zone (TDZ) begins from the start of the scope of the variable until the variable is declared.

Example demonstrating Temporal Dead Zone in JavaScript


{
 	// Start of greet's TDZ
  	let msg = 'Welcome';
	console.log(msg);

	console.log(greet); // ReferenceError because greet is in the TDZ

	let greet = 'Welcome';  // End of greet's TDZ
}

In the above code, we're accessing the variable "greet" in the temporal dead zone (TDZ).

Output

Welcome

/index.js:6
	console.log(greet); // ReferenceError because greet is in the TDZ

3. Implicit Global Variables

We know that undeclared variables, when initialized, become global variables implicitly. Such implicitly global variables behave like variables declared with the var keyword.


function VariableHoisting() {
    x = 80; // Implicit global variable
    let y = 20;
}
VariableHoisting();
console.log(x); 
console.log(y);

The variable x is an implicitly global variable; hence, it is accessed outside the function VariableHoisting(). The variable y is declared with the let keyword, and hence it becomes a local or block-scoped variable to the VariableHoisting() function. Therefore, accessing y outside the function results in ReferenceError.

Output

80

/index.js:7
console.log(y);
            ^
ReferenceError: y is not defined

2. Function hoisting in JavaScript

Like variable hoisting, where we can use the variables before the declaration, we can call the function before their definition.

Example of Function hoisting in JavaScript


// function call
greeting(); 

// function declaration
function greeting() {
  console.log("Welcome to ScholarHat.");
}

The above code calls the greeting() function before its definition due to hoisting.

Output

Welcome to ScholarHat.

If you call a function that isn't declared, JavaScript gives ReferenceError.

greet(); 

Output

greet(); 
^
ReferenceError: greet is not defined

Function Expressions Hoisting in JavaScript

The JavaScript interpreter hoists only the function declaration and not function expressions like the variable assignments.

Example Illustrating Function Expressions are not hoisted in JavaScript.


// call greet() function before declaration
greet();

// function expression
var greet = function() { }

Output

greet();
^
TypeError: greet is not a function 

// call greet() function before declaration
greet();

// function expression
let greet = function() { }

Output

greet();
^
ReferenceError: Cannot access 'greet' before initialization  

In the above two codes, the function expression is assigned to the variable greet. When we try to call greet(), it shows TypeError and ReferenceError, respectively, depending on the scope of the variables.

Function-scoped Variable Hoisting in JavaScript

We'll understand the hoisting of variables inside the function with an example.

Example of Function-scoped Variable Hoisting


function greet() {
  
    // use the variable message before declaration
    console.log(message); 
    var message;
}

//function call
greet();

console.log(message);

In the above code, the message variable is hoisted to the top of the greet() function and becomes a local variable. Because its scope is limited to the function, it's not accessible outside the function.

Output

undefined

/index.js:11
console.log(message);
            ^
ReferenceError: message is not defined

JavaScript Initializations are Not Hoisted

JavaScript hoists the declaration to the top of the scope during the compilation phase. Does the variable initialization also get hoisted? No, the initialization remains at the same place where it's done.

Example


console.log(greet);
var greet = 'Welcome to ScholarHat';

Output

undefined

The above code is equivalent to:


var greet;
console.log(greet);
greet = 'Welcome to ScholarHat';

Output

undefined

Here, the value of the greet variable is undefined because it is printed without initializing it.

Summary

Hoisting is an important JavaScript concept that is often overlooked. One must try to avoid using variables before their declaration. The best practice is to declare and initialize variables before their usage. Hoisting can make your program tricky and cause problems. Therefore, it's advantageous to be aware of the hoisting phenomena and try to avoid them as much as possible. For more such important concepts, consider our JavaScript Programming Course.

Take our Javascript skill challenge to evaluate yourself!

In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.

GET FREE CHALLENGE

Share Article
About Author
Shailendra Chauhan (Microsoft MVP, Founder & CEO at Scholarhat by DotNetTricks)

Shailendra Chauhan is the Founder and CEO at ScholarHat by DotNetTricks which is a brand when it comes to e-Learning. He provides training and consultation over an array of technologies like Cloud, .NET, Angular, React, Node, Microservices, Containers and Mobile Apps development. He has been awarded Microsoft MVP 9th time in a row (2016-2024). He has changed many lives with his writings and unique training programs. He has a number of most sought-after books to his name which has helped job aspirants in cracking tough interviews with ease.
Accept cookies & close this