This article is written as part of the series where I am writing the whole process of how Javascript files are executed by browsers. You can find the whole list of articles in order at the bottom of this article.
The literal definition of Hoisting
Most of the languages will give an error if we try to access the variables before their declaration. But not JavaScript. It's a very forgiving language. Quite interesting, no? Let's understand how and why behind this concept.
In JS, it is quite possible to access the variables even before they are declared. This is known as Hoisting in JS.
How it is happening under the hood
So when the browser encounters javascript code, it hands it over to the javascript engine present in every browser as the browser does not understand JS code.
I have covered how JS engines do a compilation of high-level JS code in machine code and how it executes JS code in-depth here
Just keep in mind that before the execution of JS code, the JS engine(interpreter) first scans the JS code line by line and the memory is allocated to all the variables & functions. So, now the JS engine is aware of all the variables and functions that are inside the file and do not give this error ReferenceError: variable/function is not defined
if one accesses them before their declaration.
Hoisting for variables declared with var
During the creation phase, the JS engine will store it in a memory space with a special value undefined
. Hence if you try to access it before its declaration, you will not get an error, and you will be able to access it with value = undefined
.
In this case, the variable declared with var
keyword in the global scope(not inside any function or block), then the variable will be stored as the property of window
which is a global object. You can read more about scopes here.
console.log(x); // undefined
console.log(window.x) // undefined
var x = 7;
console.log(window.x) // 7
Hoisting for variables declared with let
or const
In the case of variables declared with let
and const
The JS engine stores them in separate memory space but they remain uninitialized. It means, JS is aware of their existence, but we cannot access them before their declaration unlike variables declared with var
. You will get a reference error ReferenceError: variable is not defined.
let and const are features of ES6 and they were introduced to overcome this shortcoming of var.
In this case, the variable declared with let/const
the keyword in the global scope(not inside any function or block), then the variable will not be stored in window
object, instead, they are stored in some memory space(TDZ)e from which it's not possible to access them before their declaration.
console.log(x); // Reference Error: x is uninitialized
let x = 7;
function declaration hoisting
During the creation phase, memory is allocated to each function
call, and an actual copy of the function body is stored inside the memory space for function
declarations. It means not only we can access the function before its declaration, we can also invoke it. This is one of the advantages of hoisting.
getName("Krishna");
function getName(name){
console.log(`My name is ${name}); // No error
}
JavaScript only hoists declarations, not initializations!
Function expression and arrow function hoisting
const getTwenty = () => 20; // arrow function
const getRectArea = function (width, height) { // function expression
return width * height;
};
Typically, in such cases, it is the same as a value is assigned to a variable. In that case, that variable declaration is hoisted depending on how that variable is declared.
Always declare the variable before accessing it.
Temporal Dead Zone(TDZ)
As the variables declared with let
or const
are set to uninitialized during the creation phase, so they are of no use to access them before their declaration. Under the hoods, JS places these variables into TDZ(introduced in ES6) which makes them inaccessible between the beginning of the scope and the place where they are declared.
Advantage of TDZ
After ES6, TDZ makes it easier to avoid and catch errors that may occur due to accessing variables before their declarations.
pitfalls of hoisting
Accessing variables before their declaration can cause more harm than good.
if(!numProducts) deleteShoppingCart(); // numProducts = undefined, will delete the shopping cart
var numProducts = 10;
The above situation could be handled if the variable was declared before accessing it.
Never declare your variable with
var
. No one use it in prod apps. We read it for understanding of hoisting.
That's it, folks! That's all about Hoisting. Follow me for more in-depth articles. Leave your feedback in the comment section.
Further Read-
The one article about Closure to rule them all.
Upcoming articles
Settimeout intricacies
How JS handles async events
Functions in JS