Do you really know about Hoisting?
Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their scope before code execution. All variable and function declarations are hoisted to the top of their scope
However, in contrast, undeclared variables do not exist until code assigning them is executed. Therefore, assigning a value to an undeclared variable implicitly creates it as a global variable when the assignment is executed. This means that all undeclared variables are global variables.
function hoist() {
a = 20;
var b = 100;
}
console.log(a); // error a is not defined
hoist();
console.log(a); // 20 a becomes global variable
console.log(b); // error b is not defined (it is defined in hoist method scope not global)
Difference between var, let and const in terms of hoisting
All the types var, let and const get hoisted but there is a difference in the default value with which they get hoisted like in var they get hoisted with undefined value but in case of let and const they don't initialize with any value.
console.log(x); // undefined
var x = 10;
It will give undefined because only the declaration is hoisted not the initialization. So it will be interpreted as :
var x;
console.log(x);
x = 10;
The same behavior of var is in functional scope also.
function getName() {
console.log(name);
var name = "Max";
}
getName(); // undefined
To avoid this we can declare and define the variable before using it
function getName() {
var name = "Max";
console.log(name);
}
getName(); // Max
As we know in case of let the default value is not there so we cannot access the variable before the engine evaluates its value.
console.log(age); // Output: ReferenceError: age is not defined ...
let age = 25;
So the engine binds the value to the variable where it is actually declared. So if we write code like this
let age;
console.log(age); // undefined
age = 25;
In this case, undefined is printed because as in line 1 we are declaring the variable So we are binding the variable with the value and default value is undefined.
In the case of const. Much like the let keyword, instead of silently exiting with an undefined, the interpreter saves us by explicitly throwing a Reference error.
console.log(age); // Output: ReferenceError: age is not defined ...
const age = 25;
We have to declare and define the const variable together. we cannot separately so that.
const age; // Missing initializer in const declaration
Hoisting Functions
A function can declassify into 2 parts in terms of hoisting :
Function declaration Function expression
Function declaration
In a function declaration , the function is defined without a new variable like
function print(var name) {
console.log(name);
}
In case of function declaration whole function gets hoisted for example :
print("Alax"); // Alax
function print(var name) {
console.log(name);
}
Functional expression
In this, a function is assigned to a new variable
let printFn = function(var name) {
console.log(name);
}
In this case, only the variable is hoisted not the whole function
printFn(); //Output: "printFn: expression is not a function
let printFn = function(var name) {
console.log(name);
}
printFn is initialized with undefined, it's not a function when we are invoking it that's why we get this error.
Order of precedence
Function declarations take precedence over variable declarations. Variable assignments take precedence over function declarations
var name = "Tom";
function name() {
console.log("Harry");
}
console.log(typeof name); // string (variable assignment take precedence)// 2nd Examplevar name;
function name() {
console.log("Harry");
}
console.log(typeof name); // function (function declaration take precedence)
Hoisting Classes
Hoisting classes are the same as function hoisting. It also has 2 types
Class declarations
Class expressions
Class declarations
Much like their function counterparts, JavaScript class declarations are hoisted. However, they remain uninitialized until evaluation. This effectively means that you have to declare a class before you can use it.
var name = fullName();
name.firstName = "Sourav";
name.lastName = "Ganguly";
console.log(name); // Reference error!!!
class fullName {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
So we have to declare and define class on top of code where we are using it
class fullName {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
var name = fullName();
name.firstName = "Sourav";
name.lastName = "Ganguly";
console.log(name); // Output {firstName: "Sourav", lastName: "Ganguly"}
ClassExpression
Much like their function counterparts, class expressions are not hoisted.
var name = getFullName();
name.firstName = "Sourav";
name.lastName = "Ganguly";
console.log(name); // TypeError!!! getFullName is not a constructor
var getFullName = class fullName {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
};