What is Hoisting in JavaScript?
By: Sunil Sandhu
Tags: Programming, Front End Development, Web Development, JavaScript, Coding

What is Hoisting in JavaScript?

Find out what hoisting in JavaScript means, with examples of code to help explain it all

One of JavaScript’s many quirks is something known as hoisting.

Now if you are new to coding in JavaScript, it’s quite likely that you’re not writing your code perfectly just yet. So because of this, it’s highly likely that your hoisting isn’t perfect either. 😉

Do you find learning about this type of content useful? If so, get more similar content by subscribing to Decoded, my YouTube channel!

But what is hoisting?

Basically, when JavaScript compiles all of your code, all variable declarations using var are lifted to the top of their functional/local scope (if declared inside a function) or to the top of their global scope (if declared outside of a function) regardless of where the actual declaration has been made. This is what we mean by “hoisting”. Now bear in mind, this notion of ‘hoisting’ doesn’t literally happen in your code, but is rather something that happens figuratively, and relates to how the JavaScript compiler reads through your code. Hopefully that makes sense to you. Either way, continue reading and just bear in mind that when we think of “hoisting” we can visually imagine that whatever is being hoisted is being moved to the top, but in theory, no code is literally moving around.

Functions declarations are also hoisted, but these go to the very top, so will sit above all of the variable declarations.

Enough talk, let’s show you some basic examples of code to demonstrate the impact of hoisting.

If we were to write the following in our global scope:

console.log(myName);

var myName = ‘Sunil’;

Pop quiz! What do you think the console.log will output?

1. Uncaught ReferenceError: myName is not defined

2. Sunil

3. undefined

It turns out that this third option is actually the correct answer.

As we mentioned earlier, variables get moved to the top of their scope when your JavaScript compiles at runtime (which — if we exclude the use of NodeJS — at a very basic level simply means as your webpage is loading). However, a key thing to note is that the only thing that gets moved to the top is the variable declarations , not the actual value given to the variable.

Just to clarify what we mean, if we had a chunk of code and let’s say that on Line 10, we had var myName = 'Sunil' , when the JavaScript gets compiled, var myName would get moved to the top of its scope, whilst myName = 'Sunil' would stay on Line 10 (or possibly now Line 11 if var myName were hoisted up onto Line 1).

Let’s look at the same block of code from earlier, but look at how the JavaScript compiler will output the code at runtime:

var myName;

console.log(myName);

myName = ‘Sunil’;

This is why the console.log is able to output ‘undefined’, because it recognises that the variable myName exists, but myName hasn’t been given a value until the third line.

By the way…

We have named our variable myName instead of simply name as the ‘window’ object in the browser already has a name property. If we were to test this in a browser, any variables created in the global scope actually end up being part of the ‘window’ object. Therefore, creating var name = 'Sunil'; is the same as doing window.name = 'Sunil'; and therefore, creating var name = ‘Sunil'; can also be referenced by typing window.name .

So as window.name already exists (for your interest, window.name simply returns an empty string — at least in Chrome Dev Tools anyway), we don’t really get the proper sense of how hoisting works. We, therefore, chose to use myName instead! Don’t worry if that just went over your head, hoisting is like that!

And as we climb back out of that rabbit hole…

We also briefly mentioned earlier that functions are also hoisted to the top (right at the top, above where the variable declarations are hoisted).

So if we look at the following example:

function hey() {

console.log('hey ' + myName);

};

hey();

var myName = 'Sunil';

The hey() function call will return undefined still, because really the JavaScript interpreter to compiling to the following at run time:

function hey() {

console.log('hey ' + myName);

};

var myName;

hey();

myName = 'Sunil';

So by the time the function gets called, it knows that there is a variable called myName , but the variable has not been given a value. There are a couple of variants to this, which occur when using variable expressions of IIFE’s (click here if you want to read an earlier article on IIFEs) but trying to get a mental grip on all of this at once is not ideal, so I’ll leave you to research hoisting with respect to function expressions and IIFE’s by yourself.

Having said that, everything else mentioned above should help you to get a better understanding of how hoisting works.

The concept of hoisting is the reason why you may sometimes come across other people’s code where variables are declared right at the top, and then are given values later. These people are simply trying to make their code closely resemble how the interpreter will compile it in order to help them minimise any possible errors.

But what about Let and Const?

They’re also hoisted — in fact, var , let , const , function and class declarations are hoisted — what we have to remember though is that the concept of hosting is not a literal process (ie, the declarations themselves do not move to the top of the file — it is simply a process of the JavaScript compiler reading them first in order to create space in memory for them).

The difference between var , let and const declarations is their initialisation — in plain terms this simply means the value they are given to begin with.

Instances of var and let can be initialised without a value, while const will throw a Reference error if you try to declare one without assigning it a value at the same time. So const myName = 'Sunil' would work, but const myName; myName = 'Sunil'; would not. With var and let , you can try to use a var value before it has been assigned and it would return undefined . However, if you did the same with let you would receive a Reference Error .

So is there any difference between var, let and const in terms of hoisting?

Yes, if you create a var at the top level (global level), it would create a property on the global object — in the case of a browser, this is likely to be the window object. So creating var myName = 'Sunil'; can also be referenced by calling window.myName .

However, if you wrote let newName = 'Sunny'; this would not be accessible in the global window object — therefore, you would not be able to use window.newName as a reference to 'Sunny' .

The following issue is also fundamental to your understanding of how hoisting can affect your codebase.

Declarations made with var can be accessed from outside of their initial scope, whereas declarations made with let and const are not.

As we can see in the below example, declarations made with var return undefined whereas those made with let and const return errors (credit to gvlachos for raising and writing the following):

console.log(‘1a’, myName1); // undefined

if (1) {

console.log(‘1b’, myName1); // undefined

var myName1 = ‘Sunil’;

} console.log('2a', myName2); // error: myName2 is not defined

if (1) {

console.log('2b', myName2); // undefined

let myName2 = 'Sunil';

} console.log('3a', myName3); // error: myName3 is not defined

if (1) {

console.log('3b', myName3); // undefined

const myName3 = 'Sunil';

}

And there we have it!

If you enjoyed this article, we have also started creating video content! Show some love by subscribing to our YouTube channel!

Article updated on March 28th, 2019 in order to further explain hoisting in terms of let and const and also to fix typos in the article where I had referenced ‘name’ instead of ‘myName’. This article was updated again on September 22nd, 2019 as there was a mistake in one of the code blocks with regard to the use of let. An additional piece of text was added to explain that the concept of ‘hoisting’ is indeed a concept, and not a literal process.