During the creation phase, the JavaScript engine moves the variable and function declarations to the top of your code. This feature is known as hoisting in JavaScript.
when you execute JS code, JavaScript Engine creates Gobal Execution Context - which has two phases : 1) Creation and 2) Execution
how variable behaves during hoisting
scenario 1: Use of variable before it gets declare - type VAR
console.log(normalHoisting) // undefined
var normalHoisting = "Normal";
Due to hoisting feature , above code implicitly execute as:
var normalHoisting;
console.log(normalHoisting) // undefined
normalHoisting = "Normal";
Technically speaking, during the creation phase of the global execution context, the JavaScript engine places the variable normalHoisting in the memory and initializes its value to undefined.
scenario 2 : Use of variable before it gets declare - type Let/const:
Hoisting don't work with Let keyword
console.log(letHoisting) // Uncaught ReferenceError: Cannot access 'letHoisting ' before initialization"
let letHoisting = "Let Variable";
The JavaScript issues the following error:
"ReferenceError: Cannot access 'counter' before initialization"
The error message explains that the counter variable is already in the heap memory. However, it hasn’t initialized.
Behind the scenes, the JavaScript engine hoists the variable declarations that use the let keyword. However, it doesn’t initialize those variables. Notice that if you access a variable that doesn’t exist, the JavaScript will throw a different error:
console.log(randomVariable) // ReferenceError: randomVariable is not defined
var normalHoisting = "Normal";
let letHoisitng = letHoisitng";
Here is the same error for let and var
"ReferenceError: randomVariable is not defined
how Functions behaves during hoisting
Scenario 1 : How Hoisting works for declarative functions
let result=isHoistingDeclarativeFunction();
console.log(result); // true
function isHoistingDeclarativeFunction(){
return true;
}
In this example, we called the isHoistingDeclarativeFunction() function before defining it. The above code is equivalent to the following:
let result; //variable hoisting
function isHoistingDeclarativeFunction(){
return true;
} // function hoisting
result=isHoistingDeclarativeFunction();
console.log(result); // true
Scenario 2 : How Hoisting works for Function expressions and Arrow functions
console.log(isFunctionExpressionVar()); // isFunctionExpressionVar is not a function"
console.log(isFunctionExpressionLet ()); // isFunctionExpressionLet is not a function"
var isFunctionExpressionVar =function (){
return true;
}
let isFunctionExpressionLet =function (){
return true;
}
The above code is equivalent to the following after Hoisting:
isFunctionExpressionVar() is not a function because of hoisting , isFunctionExpressionVar still a variable with undefined value.
var isFunctionExpressionVar ;
let isFunctionExpressionLet ;
console.log(isFunctionExpressionVar()); // isFunctionExpressionVar is not a function"
console.log(isFunctionExpressionLet()); //Cannot access 'isFunctionExpressionLet' before initialization"
var isFunctionExpressionVar =function (){
return true;
}
let isFunctionExpressionLet =function (){
return true;
}
Same failure we can see in arrow function :
console.log(isArrrowFunction()); //Cannot access 'isArrrowFunction' before initialization"
let isArrrowFunction = () =>true;
Summary
- During variable hoisting, JS engine move the Var type variable to top, declares it and initialize with undefined value . Hence , such variables are available for use even before its declaration in code. No Error
- During variable hoisting, JS engine move the Let type variable to top, declares it but didn't initialize it . Hence , such variables are not available for use before its initialization. If try to use it, then getting Cannot access 'variableName' before initialization" error.
- During function hoisting, JS engine move the Declarative Functions to top, declares it . Hence , such Functions are available for use even before its declaration in code. No Error
- Function expressions and arrow functions aren’t hoisted. Only variable referencing the function are getting hosited. Hence
var type variable throw - "is not a function" error
let type variable throw - "Cannot access before initialization" error
Reference : javascripttutorial.net/javascript-hoisting