Variable hoisting in Javascript

Megh Agarwal
Nerd For Tech
Published in
6 min readMar 24, 2021
Photo by Artem Sapegin on Unsplash

Introduction

Let us first start by answering this question: What will be the code's output given below?

What is the output?

If you guessed the output as undefined, then you are correct! This is Hoisting. Logically, this should create an error because you are trying to access a variable declared after the log statement, but this does not happen. Why? Let us understand!

Hoisting occurs during the creation phase of the global execution context. The global execution context has two execution phases: Creation and Execution.

What happens technically?

During the creation phase, the Javascript engine adds the variable declaration to the memory and initializes it with a value of undefined. Hence, you get the value as undefined.

During the execution phase, the code will look like this:

The code will look something like this in the execution phase.

Note: The above code is just something for you to understand. The engine does not actually move the code at the top. The code remains as it was typed.

Great! This is Hoisting!

Note: Javascript only hoists declarations, not initializations. This means that whenever a declaration is encountered, it is added to the memory with a value of undefined. The actual initialized value is not added to the memory during the compile time, but is added during the runtime.

What if the variable does not exist at all?

This is a great question to understand hoisting. Hoisting occurs when the declaration exists in the Javascript code (position of the declaration also matters). Let us take an example. Let us run this code:

What is the output of this code?

The output of the code is:

So, hoisting will not work when the variable does not exist (no declaration).

What if the variable’s scope is different?

Let us understand what will happen if the variable is declared inside a function and is accessed outside of the function. Let us consider this code:

What will be the output of this code?

Logically, the count variable cannot be accessed outside due to the concept of local variables and scopes. Hence, we can guess that the output should be again an error. Here is the output:

So, we guessed it right! We cannot access the variable outside the counter() function scope. But what about hoisting? Why did not hoisting occur? The reason is because of the execution context. When the Javascript code executes, a global execution context is created. Therefore, any variables in the global scope are hoisted, but in this case, the count variable is initialized and declared in the function counter(). The counter() function has its execution context! Remember, hoisting happens in every execution context. Hence, if we add a console.log() statement before the variable's declaration in the counter function, the variable count will be hoisted. Let us test it out! The code:

What will be the output?

Yes, as we predicted, we get the output as undefined.

What if the variable with the same name is declared in different scopes?

This is again an exciting question! Let us consider this code:

What will be the output?

Let us look at the problem logically. The console.log(count) at line number 1 will print undefined due to hoisting. After this, the function counter() is added to the call stack, and the counter() function has its execution context. The console.log() at line number 5 will be again undefinedsince the variable count is hoisted in the counter() function execution context. Next, the console.log() at line number 9 will print 2since the count variable declared will be assigned a value of 2. It will look something like this in the execution phase:

It will look something like this in the execution phase.

For those who are wondering, why did not the console.log() statement — at line number 5 in the previous code — print the value: 1? This is because of the scope chain. Since the console.log() statement was within a function (local scope), Javascript will look for the variable count within the counter() function. If it encountered the variable, it would provide a reference to the encountered variable. Otherwise, Javascript will start to look for the variable in the global scope (follows the scope chain). In our case, since the variable count is hoisted within the counter() function’s execution context, Javascript returns the initialized value (undefined) stored in the memory.

Note: Hoisting occurs during the creation phase. The above process happens in the execution phase, hence Javascript could return the value of the variable.

Here is a visual representation of the execution context of the above code:

Now, this is all about variable hoisting. What about situations where hoisting occurs, but we receive an error? Let us understand them!

Let us consider an example. Have a look at this simple code, and then guess what will be the output:

What will be the output?

Well, if you guess undefined, you are not correct. Over here, things get complicated. If this code is executed, we get an error:

Why do we receive an error? This is because of something called as Temporal Dead Zone. When the engine encounters the variable with the let keyword, it will add the variable to the memory without any initialization (hoisting occurs, but without the value of undefined). The variable is initialized only when the engine encounters its actual declaration (let count = 0) during runtime. If the declaration does not consist of the initialization (let count;), then the engine will assign the count variable with a value of undefined. In summary, the variable cannot be accessed until the engine evaluates the count variable initialization during runtime. This is called as Temporal Dead Zone. We receive this error because we try to access the count variable between the variable creation and its initialization.

Note: Javascript hoists declarations (var, let, const, function, class). The only concept over here is that let and const declarations are not initialized, but var declarations is initialized with undefined.

Conclusion

Hoisting does not mean that Javascript code is moved to the top by the engine. It works on a concept called Lexical Environment. Hoisting does not only occur for variables. It occurs for declarations like classes, functions, variables. Hoisting is a default Javascript behavior. To avoid the consequences of hoisting (undefined variables), we should declare our variables at the top of the scope.

My next article would be on function hoisting in Javascript. If you liked the article, a clap would motivate me to write more such articles 😃.

--

--

Megh Agarwal
Nerd For Tech

Incoming freshman at the University of Toronto. Founder, developer, designer of Pustakdaan. Experienced web developer. Interested in research (AI, ML).