The one article about Hoisting to rule them all.

The one article about Hoisting to rule them all.

This article is written as part of the series where I am writing the whole process of how Javascript files are executed by browsers. You can find the whole list of articles in order at the bottom of this article.

The literal definition of Hoisting

Most of the languages will give an error if we try to access the variables before their declaration. But not JavaScript. It's a very forgiving language. Quite interesting, no? Let's understand how and why behind this concept.

In JS, it is quite possible to access the variables even before they are declared. This is known as Hoisting in JS.

How it is happening under the hood

So when the browser encounters javascript code, it hands it over to the javascript engine present in every browser as the browser does not understand JS code.

I have covered how JS engines do a compilation of high-level JS code in machine code and how it executes JS code in-depth here

Just keep in mind that before the execution of JS code, the JS engine(interpreter) first scans the JS code line by line and the memory is allocated to all the variables & functions. So, now the JS engine is aware of all the variables and functions that are inside the file and do not give this error ReferenceError: variable/function is not defined if one accesses them before their declaration.

Hoisting for variables declared with var

During the creation phase, the JS engine will store it in a memory space with a special value undefined. Hence if you try to access it before its declaration, you will not get an error, and you will be able to access it with value = undefined.

In this case, the variable declared with var keyword in the global scope(not inside any function or block), then the variable will be stored as the property of window which is a global object. You can read more about scopes here.

console.log(x);    // undefined
console.log(window.x)  // undefined
var x = 7;
console.log(window.x) // 7

Hoisting for variables declared with let or const

In the case of variables declared with let and const The JS engine stores them in separate memory space but they remain uninitialized. It means, JS is aware of their existence, but we cannot access them before their declaration unlike variables declared with var. You will get a reference error ReferenceError: variable is not defined.

let and const are features of ES6 and they were introduced to overcome this shortcoming of var.

In this case, the variable declared with let/const the keyword in the global scope(not inside any function or block), then the variable will not be stored in window object, instead, they are stored in some memory space(TDZ)e from which it's not possible to access them before their declaration.

console.log(x);   // Reference Error: x is uninitialized
let x = 7;

function declaration hoisting

During the creation phase, memory is allocated to each function call, and an actual copy of the function body is stored inside the memory space for function declarations. It means not only we can access the function before its declaration, we can also invoke it. This is one of the advantages of hoisting.

getName("Krishna");
function getName(name){
  console.log(`My name is ${name});  // No error
}

JavaScript only hoists declarations, not initializations!

Function expression and arrow function hoisting

const getTwenty = () => 20; // arrow function
const getRectArea = function (width, height) {  // function expression
  return width * height;
};

Typically, in such cases, it is the same as a value is assigned to a variable. In that case, that variable declaration is hoisted depending on how that variable is declared.

Always declare the variable before accessing it.

Temporal Dead Zone(TDZ)

As the variables declared with let or const are set to uninitialized during the creation phase, so they are of no use to access them before their declaration. Under the hoods, JS places these variables into TDZ(introduced in ES6) which makes them inaccessible between the beginning of the scope and the place where they are declared.

Advantage of TDZ

After ES6, TDZ makes it easier to avoid and catch errors that may occur due to accessing variables before their declarations.

pitfalls of hoisting

Accessing variables before their declaration can cause more harm than good.

if(!numProducts) deleteShoppingCart();  // numProducts = undefined, will delete the shopping cart
var numProducts = 10;

The above situation could be handled if the variable was declared before accessing it.

Never declare your variable with var. No one use it in prod apps. We read it for understanding of hoisting.

That's it, folks! That's all about Hoisting. Follow me for more in-depth articles. Leave your feedback in the comment section.

Further Read-

  1. Conversion of high-level JS code to machine code by browser

  2. The one article about Execution Context to rule them all.

  3. The one article about scopes to rule them all.

  4. The one article about Hoisting to rule them all.

  5. The one article about Closure to rule them all.

Upcoming articles

  1. Settimeout intricacies

  2. How JS handles async events

  3. Functions in JS