Hoisting in Javascript

Search for a command to run...

No comments yet. Be the first to comment.
While working on one of the feature in Leadlly, a platform designed to help students organize and maintain their self-studies, I encountered an interesting issue that got me thinking about race conditions in code. The app is designed to generate new ...

1. What is a Payment Gateway? A payment gateway is a service that facilitates online payments between buyers and sellers. It acts as a bridge between the customer, the merchant, and the bank. Payment gateways securely transmit payment information for...

JSON Web Token (JWT) is widely used for handling authentication and authorization in modern web applications. JWT allows secure and compact transmission of information between parties as a JSON object, and this information is verifiable and trusted b...

We know, as applications grow in complexity and usage, efficient, secure, and scalable data handling becomes crucial. Handling file uploads is a common requirement in web applications, especially in scenarios where users upload large amounts of data ...

Scaling backend infrastructure is one of the most critical steps in handling growing traffic and ensuring smooth operation under heavy loads. As systems grow, a single server processing all the tasks synchronously can become a bottleneck. This is whe...

One of the most confusing concept in Javascript is hoisting. Understanding hoisting is crucial for writing reliable and maintainable code.
When the browser encounters JavaScript code, it creates a special phenomenon known as the Execution Context. During the creation of the Variable Object, all variables declared with the var keyword and function declarations are stored in memory even before the program actually executes, and the value of variables is set to undefined. This means that you can use variables and functions in your code before they are formally declared. This process of storing variables and functions before execution is called hoisting.
console.log(name) //undefined
var name = 'John'
console.log(name) //John
In the example above, logging the variable name before its initialization doesn't throw an error; instead, it returns undefined.
There are two main types of hoisting in javascript:
Variable hoisting
Function hoisting
Class hoisting
Variables declared with var, let, and const are all hoisted in JavaScript, but there are differences in how hoisting works with var versus let/const.
Hoisting withvar: Variables declared with var are hoisted, allowing them to be accessed before initialization without throwing an error, albeit returning undefined. This behavior can be confusing for developers. To address this, ECMAScript 6 (ES6) introduced new keywords, let and const, which provide a more predictable behavior.
Hoisting withlet and const: let and const are also hoisted, but unlike var they are not initialized and accessing them before initialization results in a ReferenceError: "Cannot access 'variable' before initialization." This behavior highlights the presence of a Temporal Dead Zone (TDZ) for let and const declarations, where the variables exist but cannot be accessed until they are initialized.
console.log(fruit) //ReferenceError: Cannot access 'fruit' before initialization
let fruit = 'Apple'
In the above example we will get ReferenceError: Cannot access 'fruit' before initialization, instead if we have used var here instead of let, than we get the value of fruit undefined.
What is Temporal Dead Zone(TDZ)?
The Temporal Dead Zone refers to the period from the beginning of the scope where the let or const variable is declared until the point where it is initialized. During this time, accessing the variable will result in a ReferenceError, indicating that the variable cannot be accessed before initialization.
let name = 'John' //TDZ for 'fruit' starts here
console.log(name) //John
//Temporal dead zone for fruit hence error
console.log(fruit) //ReferenceError: Cannot access 'fruit' before initialization
let fruit = 'Apple' //TDZ for 'fruit' ends here
console.log(fruit) //Apple
Function hoisting shares similarities with variable hoisting. Function declarations are hoisted to the top of the scope, allowing them to be invoked before their actual placement in the code.
fruits() //Bannana
function fruits() {
console.log('Bannana')
}
In the above example we can see, that we call calling fruits function before its declaration and still printing the result
Note that only functiondeclarationsare hoisted, not functionexpressions.
If we try to call the variable that the function expression was assigned to, we will get a TypeError in case of var and ReferenceError in case of let and const.
//Case 1
fruits() // TypeError: fruits is not a function
var fruits = function(){
console.log('Bannana')
}
//Case 2
fruits() // ReferenceError: Cannot access 'fruits' before initialization
let fruits = function(){
console.log('Bannana')
}
Arrow functions, introduced in ES6, behaves like let, or const give ReferenceError if called before initilization.
fruits() //ReferenceError: Cannot access 'fruits' before initialization
const fruits = () =>{
console.log("apple")
}
Just like let and const variables, classes are hoisted to the top of the scope they are defined in, but inaccessible until they are initialized.
let apple = new Fruit("apple")
//ReferenceError: Cannot access 'fruit' before initialization
class Fruit {
constructor(name) {
this.name = name
}
}
Here, we declare a class called Fruit. We try to access this class before it was declared and get a reference error: Cannot access 'Fruit' before initialization, just like in let and const.
In conclusion, variable hoisting is a crucial aspect of JavaScript that impacts how variable declarations are processed during the compilation phase. While var exhibits hoisting behavior, it introduces scope-related issues. The introduction of let and const in ES6 addresses these problems by enforcing block-level scoping and introducing the Temporal Dead Zone.
As a best practice, it is advisable to use let and const over var to write more predictable and maintainable code. Understanding these concepts is essential for every JavaScript developer to produce good and bug-free code.