Ever wonder what's the deal with hoisting in JavaScript? 🤯 Don't fret! This article is here to help you get a good grasp of the two terms.
So relax, grab your favorite cup of coffee ☕️, and let’s get started with Hoisting.
Prerequisite: Execution Context
Before we dive into the fascinating world of hoisting, let's first understand the basics of execution context in JavaScript.
With every code execution, JavaScript creates an execution context. As part of this process, JavaScript creates a virtual object for each variable and initializes them with a value of undefined
. This ensures that even before code execution begins, variables have a designated space in memory. So, if we attempt to access a variable before it's initialized, it will return undefined
.
What is Hosting?
In the MDN document it shows like this.
JavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables, classes, or imports to the top of their scope, prior to execution of the code.
OR
In JavaScript, hoisting refers to the built-in behavior of the language through which declarations of functions, variables, and classes are moved to the top of their scope – all before code execution. In turn, this allows us to use functions, variables, and classes before they are declared.
yup i know definition wont help much, Let's unpack this with some examples.
Let consider the following -
In the above example everything seems to work as expected. This is a normal function code and output is also we get is obvious this is how code has to work but lets consider the below example.
Here, we're calling variables and functions before they're even initialized. Surprisingly, JavaScript doesn't throw an error as many other programming languages would. Instead, it treats this behaviour as perfectly normal -
this is hoisting in action!
Now let us see how it works separately for variable and function.
Hoisting in Variable
VAR
Consider this example:
Surprisingly, this outputs undefined
instead of causing chaos. How? Well, during compilation, JavaScript sets aside memory for name
and assigns it the value undefined
until it's properly initialized. It's like reserving a seat at the table before the guest arrives! 🪑
When JavaScript code is executed, it goes through a process known as the execution phase. During this phase, JavaScript creates what's called an execution context for each code execution. Think of it as setting the stage for the code to run smoothly.
As part of setting up this execution context, JavaScript allocates memory for variables but doesn't assign them any values yet. Instead, it initializes them with a special value called undefined
. This essentially reserves a spot in memory for each variable, marking it as empty or uninitialized.
Now, if we attempt to access or reference a variable before it's been assigned a value during this initialization phase, JavaScript returns the default value for uninitialized variables, which is undefined
. This behavior ensures that the code doesn't crash or throw errors when trying to access variables that haven't been explicitly defined yet.
So, in the context of hoisting, when we access a variable before it's been initialized, JavaScript doesn't throw an error. Instead, it returns undefined
, indicating that the variable exists but hasn't been assigned a value yet. This behaviour is fundamental to how JavaScript handles variable declarations and hoisting.
Let and Const
Like Var let and const are also hoisted but there is some difference, consider the following example
In the above code the output is Reference:…”
but why var give undefined and let and const give reference error.
Unlike var
, they throw a reference error when accessed before declaration. This is due to the concept of the Temporal Dead Zone (TDZ)
Temporal dead zone (TDZ)
Ever heard of it? Well, it's a bit of a mouthful, but don't worry, we'll break it down.
When we declare a variable using let
, const
, or class
, JavaScript creates what's called a "temporal dead zone" (TDZ) for that variable. Now, this TDZ is like a waiting room – it's where the variable sits before it gets its value.
During the TDZ period, which starts as soon as the block containing the variable begins and ends when the variable is declared and initialized, the variable exists, but it hasn't been given a value yet. So, if you try to access it during this time, JavaScript gets a bit cranky and throws a [ReferenceError].
But here's the interesting part: once JavaScript reaches the declaration of the variable and gives it a value, the TDZ ends, and the variable becomes accessible. If no initial value was specified during the declaration, JavaScript initializes the variable with a value of undefined
.
Now, compare this to var
variables. With var
, if you try to access a variable before it's declared, JavaScript doesn't throw an error – it just returns undefined
. This is because var
variables are hoisted to the top of their scope, giving them a head start in the code execution process.
So, why "temporal" dead zone? Well, it's because this zone depends on the order of execution, not the order in which the code is written. Take this example: even though a function using a let
variable appears before the variable is declared, it's called outside the TDZ, so everything works smoothly.
Hoisting in Functions
Ever tried calling a function before it's even declared? Well, in JavaScript, you can do just that! Unlike variables, functions don't throw an error when you try to use them before declaring them. Instead, they give you the whole function. Interesting, right?
Now, let's dive into how hoisting works with functions.
Consider this scenario:
Here, we get the output as the whole function. Ever wonder why? It's because when JavaScript runs this code, we know that function is added in the memory component as whole in the execution context and when we call this function with out initilizing it give whole function and output..
So, even if you call the function before declaring it, JavaScript already knows about it and happily executes it without any complaints.
But wait, there's a twist! When you use a function expression or an arrow function, things work a bit differently. In these cases, JavaScript treats the function as a variable. So, before the function is declared, JavaScript stores undefined
for it in memory. When you call the function without initializing it, it returns undefined
Function Declaration and arrow function:
In the above example, we get different outputs for function expression and function declaration or arrow function. Why? Because when you use function expression or arrow functions, JavaScript considers them as variables. So, before the function is initialized, JavaScript stores undefined
for it in memory. When you call the function without initializing it, it returns undefined
.
So, next time you wonder why functions behave differently than variables when it comes to hoisting, remember this little quirk!
Wrap Up
In summary, hoisting is JavaScript's behind-the-scenes magic that rearranges declarations, allowing us to use them before they're officially declared. Understanding this behavior is crucial for writing more efficient and effective JavaScript code.
So, the next time you encounter hoisting in your code, you'll know exactly what's happening behind the scenes!
Thanks for Reading! 😃
Connect with Me! 🙋🏻♀️
My Website - https://shreyajoshi.tech/
Instagram - https://www.instagram.com/codebyshreya/
LinkedIn - https://www.linkedin.com/in/codebyshreya/
Linktree - https://linktr.ee/codebyshreya
Happy Coding! 🎉
Top comments (0)