DEV Community

Cover image for DEMYSTIFYING HOISTING IN JAVASCRIPT
Lawrence Eagles
Lawrence Eagles

Posted on • Edited on

DEMYSTIFYING HOISTING IN JAVASCRIPT

Table of content contents:

  1. Hoisting and the general misconception in the JavaScript world
  2. How JavaScript works under the Hood
  3. The true concept of hoisting
  4. The dangers of hoisting
  5. Closing thoughts

1. HOISTING AND THE GENERAL MISCONCEPTION IN THE JAVASCRIPT WORLD

What is Hoisting in Javascript?

Hoisting is a JavaScript’s default behavior of moving declarations to the top.

The above definition of hoisting has spread like wildfire throughout the internet and the JavaScript community.

HOWEVER, THIS IS JUST A HUGE MISCONCEPTION ABOUT HOISTING

As a JavaScript developer, it is important you truly understand hoisting, not only because it gives you a better understanding of the language but also because this can easily earn or cost you a point during an interview section.

Kindly note, I would be using JS and JavaScript interchangeably in this article.

HOISTING HEAD FIRST
logName() // calls function
console.log(coderName); // logs coderName to the console

var coderName = "Lawrence Eagles"; // declares the coderName variable
function logName () { // declares the logName function
    console.log("Brendan Eich")
}
Enter fullscreen mode Exit fullscreen mode

At first glance, you would certainly believe the above definition (rather misconception) Is correct.

However, let us debunk this as we demystify hoisting by digesting these examples.
The above code examples would output:

logName() // returns Brendan Eich 
console.log(coderName); // returns undefined
Enter fullscreen mode Exit fullscreen mode

The key to understanding this, is the result of logging the variable. The function call most certainly behaves as if it was moved up.
In which case the processed code would be:

var coderName = "Lawrence Eagles"; // declares the coderName variable
function logName () { // declares the logName function
    console.log("Brendan Eich")
}
logName() // calls function
console.log(coderName); // logs coderName to the console
Enter fullscreen mode Exit fullscreen mode

But if this was the case the result should be:

// logName() returns Brendan Eich
Enter fullscreen mode Exit fullscreen mode
// console.log(coderName) returns Lawrence Eagles (not undefined)
Enter fullscreen mode Exit fullscreen mode

To understand what is happening here we need to understand how JavaScript really works.

2. HOW JAVASCRIPT WORKS UNDER THE HOOD

We have established a fact from our small contrived example above that if the variable and functions were indeed moved to the top by the JS engine then the results should be:

// logName() returns Brendan Eich
Enter fullscreen mode Exit fullscreen mode
// console.log(coderName) returns Lawrence Eagles
Enter fullscreen mode Exit fullscreen mode

and not

logName() // returns Brendan Eich
console.log(coderName); // returns undefined
Enter fullscreen mode Exit fullscreen mode

The key thing to note here is that the hoisted version of the code is not behaving as if the variable was moved to the top but rather as if it was declared without a value.

Hence it behaves as if the code was:

var coderName; // declares the coderName variable without a value
function logName () { // declares the logName function
    console.log("Brendan Eich")
}
logName() // calls function
console.log(coderName); // logs coderName to the console
Enter fullscreen mode Exit fullscreen mode

Here indeed we get a result consistent with the hoisted version of the code.

logName() // returns Brendan Eich
console.log(coderName); // returns undefined
Enter fullscreen mode Exit fullscreen mode
HOW JAVASCRIPT WORK UNDER THE HOOD.

When the JS engine processes your code, it creates something called the execution context. This is a wrapper around your currently running code. It consists of the global variable, the this object (you may know it as this keyword), and the variable environment of that execution context.
We would not be going in-depth into the execution context but we will dwell sufficiently on it, for here lies the buried treasure.

There are two processes involved in the creation of the execution context viz:

  1. The creation phase: During this phase, the variables and the functions are added to memory. Here the JS engine goes through your code line by line and adds all your variables to your computer's memory but it does not assign them values just yet. The functions, however, are added to memory in their entirety. That is the whole function (name and code block) is added to memory in this phase.

  2. The second phase is the execution phase: During this phase values are assigned to variables and functions are called. so even if you initialize a variable with a value it is in this second phase that that value is assigned to it. In the first phase, the value is not assigned to the variable. It is added to memory and initialized with undefined.

3. THE TRUE CONCEPT OF HOISTING

In case you don't already see it, the whole misconception occurs because of the first (creation) phase of the execution context. Before the functions are eventually executed they are already in memory during the creation phase of the execution context so the Javascript engine knows where that function, in its entirety sits in memory. It did not move it to the top.
Hence:

logName()
function logName () { // declares the logName function
    console.log("Brendan Eich")
}
Enter fullscreen mode Exit fullscreen mode
// returns Brendan Eich
Enter fullscreen mode Exit fullscreen mode

Works correctly as if the function declaration was moved to the top. But that is not the case. The function in its entirety was already added to memory during the creation phase of the execution context. So during the execution phase, the JS engine already knows where the function sits in memory and calls it.

What about variables?

The process is the same but the implementation is a little bit different. Like I noted above the variables are also added in memory during the creation phase of the execution context but no values are assigned to them. In javascript when a variable is declared without value the JS engine automatically adds a placeholder value to it which is undefined.
This explains why:

console.log(coderName); // logs coderName to the console
var coderName = "Lawrence Eagles"; // declares the coderName variable
Enter fullscreen mode Exit fullscreen mode

and

var coderName; // declares the coderName variable without a value
console.log(coderName); // logs coderName to the console
Enter fullscreen mode Exit fullscreen mode

have the same result: undefined
For this same reason anonymous functions assigned to variables are not hoisted

UNDEFINED IN JAVASCRIPT

Undefined is a primitive type in JavaScript just like String, Boolean, and Numbers. It means you have not explicitly assign any value to that variable. further you reading at MDN
Take note it is not an error
Take note it is not null Read about null here
We can make this point clearer by running

console.log(coderName)
Enter fullscreen mode Exit fullscreen mode

without declaring the variable. That is without any of the codes below.

var coderName;
var coderName = "Lawrence Eagles"
Enter fullscreen mode Exit fullscreen mode

This would throw an error.

console.log(coderName) // returns VM275:1 Uncaught ReferenceError: coderName is not defined
Enter fullscreen mode Exit fullscreen mode

Note this is different from undefined. This is an error telling you that you are trying to log a variable that is not defined anywhere. The JavaScript interpreter is saying I did not see that variable at all in memory.
However, in the case of hoisting the variable is in memory but because it is put there during the creation phase of the execution context, the JS engine assigns a special value to it which is called undefined.
It is this whole process that is confused and misunderstood by many who think that the JS engine actually moves the variable or function declaration to the top for them.

4. THE DANGERS OF HOISTING

Hoisting offers a false security. Many developers believe that the JS engine is going to move their function and variable declarations up and so consciously write bad codes. But in reality, the JavaScript engine does not do that, we can now clearly see that the JavaScript engine is only making decisions with our codes based on how it has been implemented. This can be very dangerous because one can get undefined when a real value is expected and this can be a very nasty bug, so difficult to track that I am sure you won't like the picture by the time you finish debugging.
alt Stressed programmer
Pro Tip: Think twice and code once, save yourself the debugging stress

MODERN JAVASCRIPT AND HOISTING

From es6 and above there are new ways to declare variables in JavaScript, which makes the language now safer as both let and const (the new ways to declare variables in Javascript) do not support hoisting.

console.log(coderName); // logs coderName to the console
let coderName = "Lawrence Eagles"; // declares the coderName variable
// returns VM269:1 Uncaught ReferenceError: coderName is not defined
Enter fullscreen mode Exit fullscreen mode

and

console.log(coderName); // logs coderName to the console
const coderName = "Lawrence Eagles"; // declares the coderName variable
// returns VM397:1 Uncaught ReferenceError: Cannot access 'coderName' before initialization
Enter fullscreen mode Exit fullscreen mode

would not work. They both throw errors. You are hereby encouraged to write good codes.

5. CLOSING THOUGHTS

I do hope you learned a thing or two from reading this. I would also like to hear from you in the comment section below.
Kindly visit MDN for further your reading on hoisting

Top comments (9)

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
Sloan, the sloth mascot
Comment deleted
 
Sloan, the sloth mascot
Comment deleted
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
anjusam profile image
anjusam

'let and const (the new ways to declare variables in Javascript) do not support hoisting.' is that right?
These variables are hoisted but not assigned a value 'undefined' in the compilation phase of the execution context (unlike the var variable). These variables are initialized only in the execution phase. The time between the declaration of the variable and the initialization is called the temporal dead zone and accessing this variable in this window will throw a reference error.

Collapse
 
nabheet profile image
Nabheet Madan

Great stuff

Collapse
 
ashokkasilo profile image
Ashok Kasilo

Good one brother, Thanks much!
Keep writing about this kinda misconceptions.