Javascript Hoisting

What javascript really does when it’s hoisting your variables

When I first learned about hoisting it was a very simple idea and it made sense. The explanation was that if you access a variable before it’s declared you won’t get an error because javascript will place that variable to the very top of your code but will assign it undefined.

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

But when I came across this scenario with functions something different happened.

foo(); //outputs 1
function foo() {
console.log(1);
}

It works. The explanation is that functions get “hoisted” up to the top but unlike variables, functions get their definitions. Why couldn’t they do the same with variables? I think it’s fine to code with this definition of hoisting it’s used numerous times in javascript tutorials. However, I think finding out what’s really going on under the hood will not only help you understand hoisting, but other aspects of javascript and why it does certain things.

Javascript Parsing

What does the javascript engine do when it first runs through your code? It first creates a global scope(environment) for your program to live in. This is referred to as the global execution context. Then it’s starts parsing your code. The parsing takes 2 steps. The first step quickly goes through your code to find any variable and function declarations. This first step is referred to as Compilation or Creation phase. I like to call it the hoisting phase — the very thing we are trying to figure out. Javascript is not putting all the declarations up to the top of your script, but rather it is allocating memory for all of these declarations. It will assign all variables to undefined in this step.

//Step 1
function b(
console.log(a);
){}; //the engine puts the function body into memory as a string.
b(); //the engine ignore function invocation in this step.
var a = 1; //the engine puts variable a into memory and assigns it undefined. So a = undefined.

Once it runs through all of your script it will start parsing at the top again but this time it will assign your values to your variables and also execute your function invocations. This second step is known as the Execution phase.

//Step 2
function b(
console.log(a);
){}; //the engine ignores this declaration in this step.
b(); //the engine finds the function body for b in memory and runs the function.  It will return an error when it reaches the console.log(a); statement.
var a = 1; //parsing has stopped due to the above error.

Now if YOU were to hoist variable a to the top of the script and run it. It will work:

var a = 1; //engine has reassigned undefined with 1.
function b(
console.log(a);
){}; //the engine has allocated this function to memory.
b(); //the engine finds the function body for b in memory and runs the function.  The output will be 1.

Closing Thoughts

So it seems this is a programming issue since javascript has incorporated the “use strict” and the let identifier. You can’t run into undefined variables using these mechanisms. I think the solution is just to mimic how the old fashioned way of declaring all of your variables at the top of your program. I think this is the reason why so many people relate their explanations with the term hoisting, and also why the creators of javascript implemented this behavior in the first place — I don’t know for sure. But I have a good clue now to as to why I may have undefined variables in my code and how to tackle them.