You might have heard about the “HOISTING” feature in JavaScript, weren’t you? But do you know how and when a variable or a function gets hoisted? Or how does the mechanism of hoisting help JS? And what does it actually mean to hoist?
Okay, if you weren’t aware of hosting in JS, then this article is for you; to teach you and to guide you.
What does the term “hoisting” mean in JavaScript?
Javascript has a default mechanism of declaring variables or functions even before execution and moves them to the top of its scope. When we look at the JavaScript engine execution scenario, we find that the JS engine works in a global execution context where creation and execution parts take place separately. The first step performed by the JS engine is declaring the variables and functions in its creation phase. That is, first the Javascript engine looks for the variables and functions that have been defined in the entire programme and allocates memory to them, which we call a declaration. In the execution phase, it allocates the variable or function value to the memory location. This entire process is what we call HOISTING in JavaScript.
There are two types of hoisting in JavaScript, namely, variable hoisting and function hosting. In JavaScript, the variable hoisting and function hoisting is done separately at the time of creation. Now let us look at how variable hoisting and function hoisting vary in javascript. And how does the mechanism of hosting take place in JavaScript in the case of variables and functions?
[Also Read, JavaScript Coding Interview Questions and Answers]
Variable Hoisting
In variable hoisting, the JS engine moves all the variable declarations in the code to the top of the scope or script. So now all the variables in Javascript are allocated some memory in the creation phase of the JS engine.
var a;
a = 5;
console.log(a);
Output:5
From the above example, we have seen that the code output is “5”. Here the variable a is defined with the keyword “var” and is initialised with the value 5. In the Javascript engine, the variable a is declared in the creation phase, which is called variable hoisting and is initialised with value 5 in the execution phase. Since the code is valid, we get an output of 5.
Now let us try to understand variable hoisting with another example.
console.log(test)
var test;
Ouput: undefined
The above code behaves like
var test
console.log(test);
In the above code, we see that the output of the code is “UNDEFINED” because the variable is called before its declaration in the code. Here in the JS engine creation phase, the JS engine looks for the variables in the code and mentions them as undefined by default (i.e., in the creation phase, the variable gets allocated with some memory but not with the value, hence the variable ‘test’ in the example is mentioned as undefined in the creation phase and with the value in the execution phase). Since, in the code, the variable is called to print the output before the declaration and initialisation of the variable, the output would be “UNDEFINED”, not the “referenceError” because by default the JS engine already finds and sets the value for all the variables in the code as undefined; and in the execution phase, it allocates the value to the variable.
console.log(a);
Output: Uncaught ReferenceError: a is not defined
In the above code, we get a “referenceError” because the variable ‘a’ isn’t declared in the code.
[Also Read, Closures in JavaScript: What, Why, and How?]
Variable hoisting with ‘let’ and ‘const’
Variable hoisting with “let” and “const” is different compared to the variable hoisting of “var”. The variables that are declared with the keywords ‘let’ and ‘const’ are created with some memory in the creation phase, that is, they are hoisted but not initialised, that is, they won’t be named as “undefined” by default. So when we try to run the code which consists of the variables “let” and “const”, the JS engine throws the “referenceError” and not the “undefined”.
console.log(x);
console.log(y)
let x = 5;
const y = 10;
Output: Uncaught ReferenceError: Cannot access 'x' before initialization
In the above example, we have seen that the variables that are declared with let and const keywords throw a “referenceError” while running if the variables are called before the declaration in the code. The reason for throwing a “referenceError” while we use let and const is the TEMPORAL DEAD ZONE (TDZ). Any variables that are called in the TDZ throw a reference error.
Function Hoisting:
Functions, like variables, are hoisted during the creation phase of the Javascript engine, but not as an undefined value. They get hoisted as a function in the creation phase, so we won’t get undefined even if we call a function before its declaration in the code.
Okay, let me brief you with an example.
greet();
function greet(){
console.log('Hello Everyone.')
}
Output: Hello Everyone.
As we have seen in the above code, the output is obtained even though the function is called before its declaration in the code.
But the mechanism can be reversed if the function is initialised with the variables. So we can say that function declaration is done on the creation page, not the function expressions. Let me try to explain to you with an example.
greet();
var greet = function(){
console.log('Hello Everyone.')
}
Output: Uncaught TypeError: greet is not a function
greet();
let greet = function(){
console.log('Hello Everyone.')
}
// Output: Uncaught ReferenceError: Cannot access 'greet' before initialization
If “let” and “const” are used for function expression, we get “ReferenceError” and “TypeError” is obtained with “var”.
Conclusion:
- Variables are hoisted in the creation phase of the JS Engine. When the variable is called even before the declaration in the code, the JS engine sets an UNDEFINED when we run.
- In the case of ‘let’ and ‘const’ we get a REFERENCE ERROR when we run.
- Functions are also hoisted in the creation phase but not the function expressions. So when we try to run the function expressions we get REFERENCE ERROR and TYPE ERRORS.