DEV Community

Cover image for Javascript Hoisting
Naveenchandar
Naveenchandar

Posted on • Updated on

Javascript Hoisting

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.
Hoisting
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.
JavaScript Hoisting
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);
Enter fullscreen mode Exit fullscreen mode

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,

  1. Declaration
  2. Initialization
  3. 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.
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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 ๐Ÿ™„.
Javascript-Hoisting
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
*/
Enter fullscreen mode Exit fullscreen mode

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

  1. Function Declaration
  2. Function Expression
  3. Arrow Function

Function Declaration

greetings();
function greetings(){
    console.log('Hello from dev community')
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

Function Expression

greetings(); // Ouput: TypeError: expression is not a function.

var greetings = function hoisting() {
  console.log('Hello from function expression?');
};
Enter fullscreen mode Exit fullscreen mode

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?');
};
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode
function abcd(){}
var abcd
console.log(typeof abcd)
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
copleykj profile image
Kelly Copley

"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.

Collapse
 
naveenchandar profile image
Naveenchandar

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 or const 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 with let because it is block scope so it will not be available outside the scope.
Example:

let greeting = "Hello";
    if (true) {
        let greeting = "Hi";
        console.log(greeting); // "Hi"
    }
    console.log(greeting); // "Hello"
Enter fullscreen mode Exit fullscreen mode
var greeting = "Hi";
    if (true) {
        var greeting= "Hello!";
        console.log(greeting); // "Hello!"
    }
    console.log(greeting); // "Hello"
Enter fullscreen mode Exit fullscreen mode
Collapse
 
christianbarnabechabi profile image
Christian Barnabรฉ

Not sure about this

Collapse
 
copleykj profile image
Kelly Copley

You mean you were unsure about this, but then you read my comment. Now you know and are no longer unsure ๐Ÿ˜‰

Collapse
 
robencom profile image
robencom

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.

Collapse
 
naveenchandar profile image
Naveenchandar

Exactly.

Collapse
 
robencom profile image
robencom

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!

Thread Thread
 
naveenchandar profile image
Naveenchandar

๐Ÿ˜Š๐Ÿ˜Š๐Ÿ˜Š.

Collapse
 
copleykj profile image
Kelly Copley

This is because all declarations are hoisted. Function declarations are no different than variable declarations, memory must be reserved for them as well.

Collapse
 
smlka profile image
Andrey Smolko

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=)

Collapse
 
naveenchandar profile image
Naveenchandar

I should've elaborated that part but thanks ๐Ÿ™‚.

Collapse
 
faabiopontes profile image
Fabio Pontes

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"

Collapse
 
naveenchandar profile image
Naveenchandar

Thanks for notifying, its was by mistake.
Fixed it ๐Ÿ™๐Ÿผ

Collapse
 
meyashtiwari profile image
Yash Tiwari

Very informative and helpful.

Collapse
 
naveenchandar profile image
Naveenchandar

Thank you..๐Ÿ˜Š

Collapse
 
arvindpdmn profile image
Arvind Padmanabhan

From the comments below, there seems to be confusion about var, let and const in terms of hoisting. See devopedia.org/hoisting

Collapse
 
rexgalilae profile image
RexGalilae

Stale memes but decent explanation

Collapse
 
naveenchandar profile image
Naveenchandar

Thank you ๐Ÿ™‚.

Collapse
 
tanth1993 profile image
tanth1993

thank you for your sharing. now I know more about hoisting

Collapse
 
naveenchandar profile image
Naveenchandar

๐Ÿ™‚.