DEV Community

Cover image for Hoisting in JavaScript
Hosein Pouyanmehr
Hosein Pouyanmehr

Posted on • Originally published at hpouyanmehr.com

Hoisting in JavaScript

This post was first published on my blog. You can read it at this link for a focused and better reading experience.

This article is also available in Persian here.

About this post

In this post, we will learn what JavaScript Hoisting is and how it works behind the scenes. We'll also cover its behavior in different cases.

 

Table of Contents


Definition of Hoisting in JavaScript

Based on MDN Web Docs,

"JavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables, classes, or imports to the top of their scope, prior to execution of the code."

Source: MDN Hoisting

In simple terms, before code execution, the JavaScript engine will check your code in each scope and move the declaration to the beginning (by the beginning of a scope, you can think of the first lines of a module, a script, or the current function).

Based on this definition, and with the power of hoisting in JavaScript, you can declare a variable after it has been used or initialized!

This behavior makes us able to write something like this:

a = 1; // Assignment

console.log(a); // console: 1

var a; // Declaration
Enter fullscreen mode Exit fullscreen mode

And before execution, it became something like this:

var a; // Declaration moved to the top!
a = 1; // Assignment

console.log(a); // console: 1
Enter fullscreen mode Exit fullscreen mode

You're now familiar with the general definition of hoisting. Let's dig deep into that!


Type

Before checking different aspects of types, it is important to note again that Hoisting only happens on declarations and not initializations. This means that variable declarations are hoisted, but the initialization happens where the assignment occurs.

To understand this better, pay attention to the following examples:

var a = 1;
var b = 2;

console.log(`a=${a} and b=${b}`); // result is: a=1 and b=2
Enter fullscreen mode Exit fullscreen mode
var a = 1;

console.log(`a=${a} and b=${b}`); // result is: a=1 and b=null

var b = 2;
Enter fullscreen mode Exit fullscreen mode

In the second example, hoisting happens as the console log result is not undefined. However the assignment to the variable b happens after logging the statement to the console. So, in this case b is hoisted to the top but has no value or is null at the logging line because the variable assignment is on line 5 and after using the variable.

As we have different methods of variable declaration in JS, knowing about edge cases and hoisting behavior in different circumstances is crucial.

Variable Hoisting

In JavaScript, we can define variables with different keywords, such as var, let, or const. All three get hoisted to the top. The difference is in the initialization process.

Hoisting of var

If you declare a variable, JS will hoist that to the beginning of the current scope. Up to this point, all examples are written using the var keyword. If you need a fresher, check the #defenition section example again.

Using the var declaration gets hoisted to the top and any usage of that variable before initialization, leads to the null value.

console.log(a); // console: null

a = 1;
var a;
Enter fullscreen mode Exit fullscreen mode

Hoisting of let

A variable declared with the let keyword gets hoisted as well. But if you use the variable before declaration, the result will be a ReferenceError at the runtime.

console.log('hi');

a = 1;
let a;
Enter fullscreen mode Exit fullscreen mode

This is the result after execution:

hi

ReferenceError: Cannot access 'a' before initialization
Enter fullscreen mode Exit fullscreen mode

Hoisting of const

A variable declared with the const keyword gets hoisted like previous ones. If you use the variable before the declaration it results in a syntax error and the code won't be executed at all.

console.log('hi');

a = 1;
const a;
Enter fullscreen mode Exit fullscreen mode

You get the following error immediately after running the above piece of code:

SyntaxError: Missing initializer in const declaration
Enter fullscreen mode Exit fullscreen mode

There is a phrase for this in official documents and it is "Temporal Dead Zone". They say that when you use a let or const variable before its initialization, it is in a temporal dead zone.

In simple terms, the "temporal dead zone" is the time between when a variable is created (hoisted) and when it is declared. Hoisting for let and const doesn't lead to instant memory allocation, so if you declare something on line 5 as an example, the memory allocation will happen when the execution reaches line 5. This gap is a "temporal dead zone". For the var keyword, however, the allocation happens at the hoisting time and there will be no gap.

Function Hoisting

Functions can get hoisted in JS. This is one of the hoisting benefits, where you can call your functions before defining them.

Function Declartion

A function declaration is fully hoisted. When you define a function independently using the function keyword in JS, you can call that before its declaration. Here's an example:

logOne(); // console: 1

function logOne() {
  console.log(1);
}
Enter fullscreen mode Exit fullscreen mode

Function Expression

Function expressions also get hoisted as well, but you cannot call that before the assignment. If you do so, you'll face a TypeError at the runtime.

logOne(); // console: ReferenceError: Cannot access 'logOne' before initialization

const logOne = function() {
  console.log(1);
};
Enter fullscreen mode Exit fullscreen mode

This rule will be the same for both named functions or arrow functions.

Class Hoisting

Classes are also hoisted, but you cannot use a class before declaration because of the "temporal dead zone". If you use a class before its declaration, you'll face a ReferenceError.

const myObj = new MyNumberClass(); // console: ReferenceError: Cannot access 'MyNumberClass' before initialization

class MyNumberClass {
  constructor() {
    this.value = 1;
  }
}
Enter fullscreen mode Exit fullscreen mode

Why does Hoisting exist in JS?

JavaScript parses the code before execution, and with hoisting, it can let the interpreter know about the existence of variables and functions. This can help the interpreter to:

  1. Use functions before the declaration and be sure about their existence.
  2. Make the code more flexible to write as declaration order doesn't matter. (Improve DX or Developer Experience in my book)

References

The provided article is a try to make the following resources' contents easier to understand and unified, an all-in-one hoisting learning resource. Check them out if you want!

Conclusion

Although hoisting is the default behavior of JavaScript, it actually is a weird way of interpreting the scripts. If a developer doesn't know hoisting or doesn't understand that completely, it may lead to issues and bugs in the application.
So to avoid headaches and issues, Always declare all variables at the top of the scope!

Hope you've enjoyed this article and extended your knowledge.

Top comments (0)