Hoisting is one of the important concepts every javascript or its related frameworks developers should be familiar with. Ever wonder how function calls or variable access can be done even before declaring those. If that's so then, Welcome to Javascript Hoisting World!!!.
What is Hoisting?
This is one of the most common interview questions in front end development and common answer will be
All variable and function declarations are moved to top.
Really???๐ฎ
Hoisting is not what you think!!!๐
Let us discuss and clarify everything regarding hoisting in today's post.
Misconception
If you are trying to search and learn about hoisting, almost everywhere you will be seeing the same definition. May be that's beginner friendly but definitely that's not true. In JavaScript, Nothing will be moved.
Let's discuss in detail.
Before we start, let us understand how our code will be executed in javascript engine.
JavaScript engine runs through our code twice. First time (creation phase) - the engine goes through the code and allocates memory for the declarations of variables and functions. Second time(Execution phase) is where it actually executes our code by going through it line by line, doing the assignments, calling the functions and so on..
Variable Hoisting
Variables are one of the fundamental blocks of any programming language, the way each language defines how we declare and interact with variables can make or break a programming language. Thus any developer needs to understand how to effectively work with variables and their properties.
console.log('myName',myName);
var myName = 'JavaScript';
console.log('myName',myName);
If you look at the above example and when you try to run the code, it will not throw error. First one will be undefined
and second one will be Javascript
.
This is because no matter how are declaring variables, Javascript will always go through these lifecycles to declare a variable,
- Declaration
- Initialization
- Utilization.
So,
According to this lifecycle, the above example code will be split into
var myName -> Declaration
myName = 'JavaScript' -> Initialization
console.log('myName',myName); -> Utilization.
So,in the first run javascript will check for the declarations of variables/functions and allocates memory space. This is where all the variables will be declared with a default value undefined
and in the second run while running through all the code it will assign the actual value for it.
Actual definition
Javascript actually scans the code and takes all the variables and allocates separate memory space even before executing the code. Its just variable declarations are executed first, so they will be in reserved memory. MDN.
After introduction of ES6, Variables in Javascript can be declared by three types: var,let and const.
Another misconception is variable declared using var is only hoisted and let and const are not hoisted.
But that's not true. As per definition all the variable and function declarations are hoisted. But let
and const
hoisted a bit different.Let
and const
are hoisted in block scope whereas var
is hoisted in global scope. (Scope is another important concept which we will discuss in future post).
console.log('myName',myName);
let myName = 'Javascript';
If you run the above code, you will be getting an error
Uncaught ReferenceError: myName is not defined.
It's not the same case when you declare variable using var.
Wait how's that??๐ค
Here comes a term called Temporal Dead Zone(TDZ).
We are already in a middle of understanding one sci-fi term hoisting, but here comes the another sci-fi term called Temporal Dead Zone ๐.
So, what exactly is Temporal Dead Zone?
It is Time taken between declaring the variable(using let
or const
) and initializing the variable.
Let's go to the same code and will see why it shows reference error.
/*
let myName;
//Beginning of the temporal dead zone
console.log(firstname); // ReferenceError as accessed in the TDZ.
let myName = 'Javascript'; // Ending of the temporal dead zone
*/
Usage of Let
and const
is recommended because unlike var
, thereโs no risk of variable leakage outside of the scope of execution unless if needed. To learn more about var,let and const declarations, Please refer this link
Function Hoisting
Functions are one of the fundamental building blocks in JavaScript.
There are multiple ways to declare a function. Common ways to declare a functions are
- Function Declaration
- Function Expression
- Arrow Function
Function Declaration
greetings();
function greetings(){
console.log('Hello from dev community')
}
If you run this example it won't throw any error because greetings will be declared on the first run by javascript engine due to hoisting.
greetings();
function greetings(){
console.log('First',message);
var message = 'Hello from Dev Community';
console.log('Second',message);
}
If you run this code, first console will display undefined
because variables declared inside functions will be hoisted only top of the particular scope (code blocks). So the code will be
greetings();
function greetings(){
var message;
console.log('First',message);
message = 'Hello from Dev Community';
console.log('Second',message);
}
Function Expression
greetings(); // Ouput: TypeError: expression is not a function.
var greetings = function hoisting() {
console.log('Hello from function expression?');
};
JavaScript returns a TypeError
because unlike function declaration, only the variable was hoisted. When variables declared with var are hoisted, they are given a default value of undefined
. JavaScript then throws an error because the value of the variable is not a function at that point of time.
Arrow Functions
greetings(); // Ouput: TypeError: expression is not a function.
const greetings = () => {
console.log('Hello from arrow functions?');
};
This works same as function expression due to hoisting.When using arrow functions, or any other function expression, we must always define the function before we call it. Accessing variables before declaration is often a root cause of errors. To clarify
Only function Declarations are hoisted.
Order Of Precedence
Always function declarations are given high priority than variable declarations as per ECMAScript, section 10.5
var abc;
function abc(){}
console.log(typeof abc)
function abcd(){}
var abcd
console.log(typeof abcd)
If you run the above code, no matter what order you declare it, javascript engine will always gives high priority to function declarations than variable declarations.
Conclusion
Letโs summarise what weโve learned
- Hoisting is a process that declares variables and functions into memory space ahead of assignment and initialization within the given scope of execution.
- Only variable declarations and function declarations are hoisted.
- const and let will be hoisted but cannot be read or accessed before their initialization.
- function declarations are given high priority than variable declarations while hoisting.
To avoid confusion of hoisting and issues, itโs better to declare variables and functions before accessing them. Youโll avoid plenty of bugs and undefined warnings filling your console.
I hope this clarifies how hoisting works in JavaScript. It's definitely not a complicated one as it sounds, but it requires us to breakdown the different use cases and trying different scenarios to understand how things work under the hood.
Thanks for reading this post. Have a great day๐.
Let's meet on the next post with another Javascript concept.
Top comments (20)
"Let and const are hoisted in block scope whereas var is hoisted in global scope."
Actually var declarations are hoisted in function scope, and variables that are initialized without var, let or const are hoisted globally.
Yep missed that one. That depends on the declaration. If that's inside particular block, it'll not get hoisted globally and if not,
Let
orconst
will be hoisted globally but due to temporal dead zone we can't access those until initialization."Let and const are hoisted in block scope whereas var is hoisted in global scope." -> Whenever we try to re declare a same variable using
var
inside a specific block, variable will get updated and that's not the same case withlet
because it is block scope so it will not be available outside the scope.Example:
Not sure about this
You mean you were unsure about this, but then you read my comment. Now you know and are no longer unsure ๐
so in a nutshell: only variable declarations are hoisted (elevated to the top of the code) to not throw any ERRORS, but of course these variables are undefined; but when it comes to functions, if they are not arrow functions or function expressions, then the function is TOTALLY hoisted.
Exactly.
Great article really. I was recently asked this question in a interview, I blabbered something and even the interviewer didn't understand what hoisting really is, so my answer passed :D but now I know what to say.. MANY THANKS!
๐๐๐.
This is because all declarations are hoisted. Function declarations are no different than variable declarations, memory must be reserved for them as well.
you said about TDZ:
"It is Time taken between declaring the variable(using let or const) and initializing the variable."
IMHO It will be super useful to mention when exactly let/const variables declaring/creating. The answer - when new scope is instantiated. So TDZ always starts from the first line of the scope and ends at line with let/const a =...
and like for attempt describe hoisting for let/const=)
I should've elaborated that part but thanks ๐.
What's up, very nice article. Didn't know about the high priority, JavaScript always with it's surprises.
There's a typo in "Javascript will always go through these lifecycles to delcare a variable"
Thanks for notifying, its was by mistake.
Fixed it ๐๐ผ
Very informative and helpful.
Thank you..๐
From the comments below, there seems to be confusion about var, let and const in terms of hoisting. See devopedia.org/hoisting
Stale memes but decent explanation
Thank you ๐.
thank you for your sharing. now I know more about hoisting
๐.