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

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.

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 🙄.
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
*/

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')
}

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.

14