Hoisting

What will John see in the console, if he run the below snippet?

var x = 10;
function doSomething(){
console.log(x);
var x = 20;
}

Most likely, John’s answer will be 10. In case, if John happens to be a clever student, he may answer 20 (because 10 looks too straight to be the correct answer).

If his master asks why, then clever John will tell, it was because of hoisting (as his master has written ‘today’s topic’ at the heading or on the whiteboard.

But the master is too smart. 20 is not the correct answer. And not even 10. Then what else? If the master rule out both the options, then any good developer like John, will answer ‘undefined’. And that is the right answer.

But why ‘undefined’?

To understand that, we need to know more about variables. The master assumes, we all have the answer for the following questions:

  1. What is a variable?
  2. Why we use a variable?
  3. How to use a variable?

Now the master will ask the relevant question. Where does a variable live?

Variables live in the enclosing function. If a variable is declared in a nested function, then the variable lives only in the immediate ancestor (parent). If we declare a variable not inside any function, then it is known as global variable and it lives throughout the webpage.

In programming languages like C, we need to declare the variables at the beginning of our program. This is essential, so that the compiler can do the necessary job (which we don’t know) to take care of the variables.

But in javascript, there is no need to declare the variables at the beginning and it kindly offers the developers, the freedom to code the way they like it. But unfortunately the compiler (or interpreter) still has the job, to be aware of the variables, before executing the code.

To address this issue, javascript compilers hoist the variables to the top of the place, in which they live. Either to the top of the function, or to the beginning of the script tag if there is no enclosing function.

This is little difficult to comprehend, because we know that computer will run our program in a linear manner, from first line to last line. If the master tell John that the computer will juggle some of the lines in the code that he writes, John will doubt that.

But after going though his mind, the necessity for compilers to be aware of the variables before executing the code, John is somehow convinced.

But now a sudden spark comes in John’s mind and confront his master, “Master! if variable hoisting happens, then my answer 20 should be correct.”

The master smiled. “Only the variable declaration gets hoisted and not the variable initialization”. When we write var x = 10; we actually do two things:

  1. We are declaring the variable and
  2. we are initializing the variable

In case of variable hoisting, only variable declaration gets hoisted. Variable initialization will remain at its original place. After hoisting, our example code looks as below and the it logs ‘undefined’ in console.

var x = 10;
function doSomething(){
var x;
console.log(x);
x = 20;
}

Even seasoned developers are not familiar with variable hoisting, as their daily work doesn’t demand them. But once in a while, we may encounter bugs due to this hoisting behavior.

Just like variables, functions are also hoisted. And to find where it will get hoisted, we need to answer the same question. Where the function lives? Remember, the behavior of function is much similar to that of a variable.

In fact, most of the developers have relied on hoisting in their daily work, even without being consciously aware of it. How many times, have we made a call to a function, or used a function before declaring them?

myBtn.addEventListener("click", onBtnClick);
function onBtnClick(event){
//...
}

Very commonly we write like this. We added the listener first and later we define the listener function. This will work fine and the function will be hoisted.

But the below snippet will not work as the callback is assigned to a variable. As you can guess, the variable declaration alone gets hoisted, and not the variable initialization.

myBtn.addEventListener("click", onBtnClick);
var onBtnClick = function(event){
//...
}

What will get logged in console, if we run the below snippet?

function doSomething(){
do();
return;
function do(){
console.log('hello world');
}
}
doSomething();

The answer is ‘hello world’. It has been deeply ingrained in us that anything after the ‘return’ statement will not work. But the function declared after the ‘return’ statement will get hoisted to the top of the ‘doSomething’ function.

Conclusion

The variables and functions declared in javascript will get hoisted to the top of

  1. the enclosing function or
  2. to the beginning of the script, if there is no enclosing function.
Show your support

Clapping shows how much you appreciated Rethna Ganesh’s story.