Javascript Hoisting Concept

Hoisting

Hoisting is a concept in javascript in which all the variables or functions declarations moved on the top of their respective scope. Both the variables and functions declarations moved on the top of their global or local scope. The main advantage behind this concept is that we can call functions or use variables by storing them in memory before even running the code. All the declarations for functions and variables got moved on the top. 

var a = 10;

The above statement includes two steps: declaration and initialization. It can be written in two steps as follows:

var a;  // declaration
a = 10; // initialization

Note: All the undeclared variables are assigned global scope in javascript.

Now we will see how hoisting works:

console.log(a); 
var a = 100; // output will be undefined here

The compiler applies to hoist here as follows. Therefore we got undefined as it is not initialized. We got undefined instead of ReferenceError as hoisting gets applied. The declaration of the variable moves to the top.

var a;
console.log(a); 
a = 100;

Now if we call a function before its declaration, it still works.

hoisting();

function hoisting(){
 var a =10;
 let b= 12;
 console.log(a);
 console.log(b);
}

The output will be as follows:

10
12

We can call the function before its declaration as function declarations are also hoisted. 

function hoisting() {
  x = 1;
  var y = 2;
}
hoisting();
console.log(x); 
console.log(y);

The compiler reads it as:

var x;
function hoisting() {
  var y;
  x = "Hello World"; // This variable will gets hoisted to global scope
  var y = "hi"; // This variable will get hoisted to local scope
}
hoist();
console.log(x);
console.log(y);

The output will be:

'Hello World'
error: Uncaught ReferenceError: y is not defined

Hoisting with var, let and const keyword

The following example shows how hoisting works with var and let keywords.

function calc(){
 console.log(a);
 console.log(b);
 console.log(c);
 var a = 10;  
 let b = 12;
 const c = 13;
}
calc();

We will get the below error:

Uncaught ReferenceError: Cannot access 'b' before initialization

Temporal Dead Zone: Variables that are declared using let and const keyword are hoisted but assigned as uninitialized in the lexical environment. When JS engine runs during run time then only it will get initialized. So for a particular amount of time, until the engine reaches the declaration, we can't access the variable which is declared using let and const. This time span is called the temporal dead zone. If the javascript engine reaches the declaration and check that value is not defined then it will assign undefined. 

Function expressions are not hoisted but function declarations do.

Function expressions are not hoisted:

Hoist();  // TypeError: helloWorld is not a function
var Hoist = function(){
  console.log('Hello');
}

We will get the TypeError as function expressions are not hoisted in javascript. If we call the function before its declaration, then it will throw an error.

error: Uncaught TypeError: noHoist is not a function

Now we will see how var and let scope works using an example:

function scopeVar() { 
  var a = "hi"; 
 if (true) { 
   var a = "hello"; // Here a is the same variable but new value is assigned
   console.log(a); 
 }
 console.log(a);
}

function scopeLet() {
 let b = 1; 
 if (true) {
   let b = 2; 
   console.log(b); // Here different b is there as let keyword has block scope
 }
 console.log(b); 
}

scopeVar();
scopeLet();

The output will be:

'hello'
'hello'
2
1

Comments