Hoisting in JavaScript

  • In the first snippet, the function is declared first, and called (used) later.
  • In the second snippet, the function is called (used) first, but declared later.
  • Normally you need to declare your variables and function first, then after you can use it.
  • That's how the code execution works, it starts from the top. The execution thread needs to know that a value/function exists before it can be used/called.
  • But with a few declarations like a function declaration: you can call the function even before you have declared it, 
  • That's Hoisting in JavaScript.

Hoisting in JavaScript

  • What is Hoisting?

Hoisting is a JavaScript mechanism where the JavaScript interpreter moves all variable and function declarations to the top of the current scope before the code execution starts.

Because of this, we're able to access these functions and variables before their declaration.

Scenarios of hoisting in JavaScript:

  • var hoisting
  • let and const hoisting
  • variables inside functions
  • Function declaration hoisting
  • Function expression hoisting
  • Arrow functions hoisting
  • Class declaration hoisting
  • Class methods hoisting

Hoisting in JavaScript

Hoisting in JavaScript

Although JavaScript is an interpreted language, it still gets all the declarations stored in memory, before it starts executing the code.

This task is accomplished by the JavaScript interpreter. How?

The JavaScript interpreter runs through the entire code, twice.

Hence, there are two phases in JavaScript code execution:

  1. Interpreter's first run -
    Creation or Hoisting Phase or Compile Run
     
  2. Interpreter's second run -
    Code Execution Phase

Deep dive into Hoisting in JavaScript

  • In the first run, the interpreter goes through the entire code, picks up all the declarations (function, variables, class, etc.) along with their lexical scope, and assigns memory to them in the memory heap.
     
  • All declarations, in any scope (inside functions too), are hoisted at the top of their lexical scope.
     
  • Imp: Only declarations are picked by the interpreter for hoisting, not their values (left hand part of "=" assignment operator).

1. Interpreter's first run - Creation or Hoisting Phase or Compile Run

Hoisting in JavaScript

  • Different declarations are hoisted differently by the interpreter in the memory heap. For example:
    - a var declaration is initialised with a value of undefined during hoisting, but
    - a let or const declaration is not initialised during hoisting.
     
  • During the first run, the interpreter also performs optimizations on the code such as verifying the syntax and optimizing for better performance.
     
  • Hoisting is done during the interpreter's first run through the code.
function wrapper() {
    console.log({bottom})
    var bottom = 100
}
wrapper()
// { bottom: undefined }

Hoisting in JavaScript

  • During the execution phase, the JavaScript engine executes the code line by line, synchronously.
     
  • In this phase, the interpreter assigns the values to variables stored in the memory heap during the hoisting phase and executes the function calls.

2. Interpreter's second run - Code Execution Phase

Hoisting in JavaScript

  • var hoisting
  • let and const hoisting
  • variables inside functions
  • Function declaration hoisting
  • Function expression hoisting
  • Arrow functions hoisting
  • Class declaration hoisting
  • Class methods hoisting

Understanding different scenarios of Hoisting

Hoisting in JavaScript

var hoisting:

var variables are hoisted (lifted to the top of the scope), and initialised with a value of undefined,

function checkVarHoisting(){
  console.log({custom}) // undefined
  var custom = 100;
  console.log({custom}) // 100
}
checkVarHoisting()

// Step 1
// Hoisting phase - First Run
function checkVarHoisting(){
  var custom = undefined
  
//   console.log({custom})

//   console.log({custom})
}
checkVarHoisting()
// Step 2
// Execution phase - Second Run
function checkVarHoisting(){
  var custom = undefined
  
  console.log({custom}) // undefined
  custom = 100
  console.log({custom}) // 100
}
checkVarHoisting()

Hoisting in JavaScript

function checkVarHoisting(){
  // Reference Error: Cannot access 
  // before initialisation
  console.log({custom})
  let custom = 100;
}
checkVarHoisting()

let and const hoisting:

  • variables declared with let or const are not hoisted in the global scope. They give Reference error.
  • Inside a function, they are hoisted, but differently.
  • If they are accessed before their declaration, they give reference error, but also acknowledge that a variable with the name is declared down the line.
  • They give reference error clearly mentioning that you're accessing a variable before but it is declared later.
// Reference Error: not defined
console.log({custom})
let custom = 100;

Hoisting in JavaScript

function checkVarHoisting(){
  for (let i = 0; i < 10; i += 1){
    console.log({i})
  }
  console.log({custom})
  
  let custom = 100;
}
checkVarHoisting()

/**
 * Line 2 - 6 is TDZ
 * for variable "custom"
 * If "custom" is accessed
 * before line 7, it gives
 * Reference Error: cannot
 * access before initialisation
*/

TDZ - Temporal Dead Zone

 

  • For a variable declared using let or const inside a function, the line or space before the declaration of that variable, where that variable is NOT accessible, is called the Temporal Dead Zone of that variable.
  • If the variable is tried to access in its Temporal Dead Zone, it gives Reference Error: cannot access before intialisation

Hoisting in JavaScript

function checkVarHoisting(){
  for (let i = 0; i < 10; i += 1){
    console.log({i})
  }
  
  function inner() {
    // ReferenceError: 
    // Cannot access 
    // 'custom' before initialization
    console.log("inside", {custom})
    let custom = 100;
  }
  inner()
  
}
checkVarHoisting()

TDZ - Temporal Dead Zone

  • This TDZ of a variable exists only in the scope where that variable is defined.

Hoisting in JavaScript

function checkVarHoisting(){
  for (let i = 0; i < 10; i += 1){
    console.log({i})
  }
  // ReferenceError: 
  // 'custom' is not defined
  console.log("inside", {custom})
  
  function inner() {
    let custom = 100;
  }
  inner()
  
}
checkVarHoisting()
func123()
func246()

function func123(){
  for (let i = 0; i < 10; i += 1){
    console.log({i})
  }
  console.log({custom})
  
  let custom = 100;
}

function func246() {
  console.log({"func246"})
}

Function Declaration Hoisting

 

Function declarations are hoisted to the top of their current scope.

They are hoisted along with their definitions, so they can be called in the code before their declaration

Hoisting in JavaScript

Hoisting in JavaScript

  • var - hoisted (initialised with undefined)
  • let and const - hoisted (not initialised, TDZ - temporal dead zone)
  • variables inside functions - hoisted like above
  • function declaration - hoisted to the of the scope, with definition
  • function expression - Not hoisted
  • arrow functions - Not hoisted
  • class declaration - Not hoisted
  • class methods - Not hoisted

Hoisting in JavaScript

By Yash Priyam

Hoisting in JavaScript

  • 113