Understanding hoisting in javascript
Inside a particular file, Javascript doesn't care where you declare your custom functions.
Let me elaborate.
We have worked on creating two components so far:
- Modal
- Accordion
1) Modal
function showModal(){
let discountModal = document.querySelector("#surprise-discount-modal");
discountModal.style.display = "block";
}
let showModalButton = document.querySelector(".show-modal-btn");
showModalButton.addEventListener("click", showModal);
While working on the modal project, we first declared the showModal
function at the top of the index.js
file.
And we are using it at a later time in the code by providing it as the event handler to the addEventListener
method:
showModalButton.addEventListener("click", showModal);
Simply put, in this case, we are declaring the function first and then using it.
2) Accordion
const accordionHeader = document.querySelector(".accordion .accordion-header");
accordionHeader.addEventListener("click", toggleAccordionContent);
function toggleAccordionContent(){
const accordion = document.querySelector(".accordion");
accordion.classList.toggle("is_open");
}
But while working on the Accordion project, we have declared a custom function called toggleAccordionContent
at the end of the index.js
file.
But we are using it earlier in the code by providing it as the event handler to the addEventListener
method:
accordionHeader.addEventListener("click", toggleAccordionContent);
Simply put, in this case, we are using the name of the function before it is even declared.
But the code and functionality of the accordion still work as expected.
This raises the question.
Shouldn't we declare a function before using it?
And the answer is simple.
Javascript doesn't care where you declare your custom functions.
As long as the function is declared, it doesn't matter where you declared it inside a javascript file.
When the web page is loaded, the browser doesn't start executing the code inside the javascript file immediately.
If we go into the details, the browser doesn't execute the javascript code at all.
Instead, every browser comes with something called a javascript interpreter and it is the responsibility of the interpreter to execute the javascript code.
And when the interpreter sees the code inside the javascript file, before executing the code line by line, it first parses the entire javascript file.
This way, it knows all the functions and variables that are declared beforehand.
In fact, it even moves all the functions and variables declared to the top of the file.
For example, when writing the code, we have declared the function toggleAccordionContent
function at the end of the index.js
file:
const accordionHeader = document.querySelector(".accordion .accordion-header");
accordionHeader.addEventListener("click", toggleAccordionContent);
function toggleAccordionContent(){
const accordion = document.querySelector(".accordion");
accordion.classList.toggle("is_open");
}
But when the interpreter starts processing the index.js
file, it moves the declaration of toggleAccordionContent
function to the top of the existing code:
function toggleAccordionContent(){
const accordion = document.querySelector(".accordion");
accordion.classList.toggle("is_open");
}
const accordionHeader = document.querySelector(".accordion .accordion-header");
accordionHeader.addEventListener("click", toggleAccordionContent);
This is also called Hoisting in javascript.
Hoisting generally means raising.
Simply put, the javascript interpreter simply hoists all the function declarations to the top of the file.
And only after the hoisting process is complete, it starts executing all the code line by line.
And this is why we were able to use the name of the function before it is even declared.
const accordionHeader = document.querySelector(".accordion .accordion-header");
accordionHeader.addEventListener("click", toggleAccordionContent);
function toggleAccordionContent(){
const accordion = document.querySelector(".accordion");
accordion.classList.toggle("is_open");
}
So, when we write our javascript code inside a particular file, we don't really have to worry about where we declare the functions inside the particular file.
One last example.
Imagine that a web page needs both the modal and accordion functionality and we have written our javascript code in the following way:
function toggleAccordionContent(){
const accordion = document.querySelector(".accordion");
accordion.classList.toggle("is_open");
}
let showModalButton = document.querySelector(".show-modal-btn");
showModalButton.addEventListener("click", showModal);
let hideModalButton = document.querySelector(".hide-modal-btn");
hideModalButton.addEventListener("click", hideModal);
const accordionHeader = document.querySelector(".accordion .accordion-header");
function showModal(){
let discountModal = document.querySelector("#surprise-discount-modal");
discountModal.style.display = "block";
}
accordionHeader.addEventListener("click", toggleAccordionContent);
function hideModal(){
let discountModal = document.querySelector("#surprise-discount-modal");
discountModal.style.display = "none";
}
Basically, we have messed up everything :P
But the modal and the accordion still work well.
That's how flexible hoisting in javascript is.
Having said that...
The recommendation
It is recommended to declare the functions before using them and at the top of the file because:
- It keeps our code organized
- We don't have to stressfully hunt where a particular function is declared.
- We don't get confused, and it saves a lot of time.
- On top of that, we are slightly improving the performance of our code because the interpreter doesn't have to do the extra step of moving the declarations to the top.
So, declare the functions at the top and use them later.
Anyway, this is all great.
But if you want to avoid the problem of your code running all over the place, there is a better way of declaring functions.
In the next lesson, we will learn about anonymous functions.