Hoisting in JavaScript

Hoisting in JavaScript

How Hoisting Works in JavaScript — Variables and Functions

What is Hoisting in JavaScript?🤔

Hoisting is a very important process in JavaScript that’s made by the interpreter. The interpreter moves the declaration of functions and variables to the top of their scope, prior to the execution of the code. This feature is known as hoisting in JavaScript.

Variable Hoisting

In JavaScript, we can declare variables with const, let, and var. I will explain in detail each variable declaration type individually because the behavior is not the same when hosting.

var hoisting 🧐

Let’s look at some 😉examples to understand hoisting in the case of var variables.

console.log(a); // outputs 'undefined'
var a = 3;

We expected 3 but instead got undefined. Why?

Remember JavaScript only hoists declarations, not initializations. That is, during compile time, JavaScript only stores function and variable declarations in the memory, not their assignments (value).

But why undefined?🧐

When the JavaScript engine finds a var variable declaration during the compile phase, it will add that variable to the lexical environment and initialize it with undefined, and later during the execution when it reaches the line where the actual assignment is done in the code, it will assign that value to the variable.

So the initial lexical environment for the above code will look something like this:

lexicalEnvironment = {
  a: undefined
}

That’s why we got undefined instead of 3. And when the engine reaches the line (during execution) where the actual assignment is done, it will update the value of the variable in its lexical environment. So the lexical environment after the assignment will look like this:

lexicalEnvironment = {
  a: 3
}

Why it’s helpful?🥸

It’s helpful because we will not receive the error of Uncaught ReferenceError: a is not defined, and instead of it, we will receive undefined as the returned value.

What are the differences?🥸

When we receive the error of Uncaught ReferenceError: a is not defined, it means that the variable a is never declared, and when we receive a return value of undefined, it means that the variable is declared but not initialized or assigned to the value 3 as it happens somewhere in the code; instead, the hoisting process initialized the a variable to the default value undefined.

Const & Let Hoisting💥

So are let and const variables not hoisted?🤫

The answer is a bit more complicated than that. All declarations (function, var, let, const and class) are hoisted in JavaScript, while the var declarations are initialized with undefined, but let and const declarations remain uninitialized.

Here come the big differences between var and const/let hoisting. Behind the scenes, variables that are declared with let and const are also hoisted, but unlike var, they do not receive the default value of undefined.

So what happens if we call const/let variables before they are initialized?🤔 We will get an error: Uncaught ReferenceError: can’t access lexical declaration ‘myName’ before initialization.

console.log(myName); // Uncaught ReferenceError: can’t access...
function message(){
  console.log("Hello World!");
}
const myName="chhakuli zingare";

Function Hosting😯

This type of hosting is very important and really makes our code safer. Let’s illustrate it by an example.

message(); //Will print to the console "Hello World".
function message(){
  console.log("Hello World");
}

As we can see in the example above, we call a function that’s not yet declared, but still, it will work absolutely fine. That’s because ‘function hosting’ is involved. Behind the scenes, the declaration of the function message is moved to the top of the JavaScript file. This means that actually, the function call is made after the declaration and not before it.

This magic protects our code from wrong calls that may be made before the function declaration.

Arrow Function Hosting 🏹

The hosting behavior of arrow functions and regular functions are not the same. Let’s take a look at the example below:

message(); //Uncaught TypeError: printSomething is not a function.
var message=> (){
  console.log("Hello World");
}

Why does that happen?

The hosting behavior of arrow functions are like the keywords const, var, let and when we try to call the message function, we receive the error Uncaught TypeError: message is not a function. Let’s think about the steps behind the scenes:

  • The message is a var variable, so because of that, it goes to the top of the JavaScript file.
  • The variable message received the default value of undefined.
  • We try to call the arrow function message, but it’s still defined with the value of undefined.
  • The error Uncaught TypeError: message is not a function occurs.

Conclusion🙆‍♀️

So now we know that during hoisting our code is not physically moved by the JavaScript engine. Having a proper understanding of the hoisting mechanism will help you avoid any future bugs and confusion arising due to hoisting.

To avoid possible side effects of hoisting like undefined variables or reference error, always try to declare the variables at the top of their respective scopes and also always try to initialize variables when you declare them.

Did you find this article valuable?

Support Chhakuli Zingare by becoming a sponsor. Any amount is appreciated!