How Javascript Really Works - Part 4

May 2, 2022 •☕ 3 min read
Hoisting

In the previous parts, we built the building blocks of how Javascript works behind the scenes. But either at this point, if you ask yourself how exactly your code is being read by the Javascript Engine, will you be confident about your answer? Even if we ask experienced developers this question, many will come with the answer “Of course it is being read from top to bottom, line by line”, and many others won’t be so sure about what to answer you. Although this answer is essentially correct, if you build your Mental model around this principle, this may lead to several misconceptions about your code.

Let’s see some examples. What will the output be in the console from the following snippet?

showInConsole();

function showInConsole() {
    const a = 5;
    console.log(a);
};

It will be, of course, the value 5. But how are we able to execute a function before its declaration if our code is being read from top to bottom?

Let’s introduce the concept of Hoisting. Hoisting in general, is a mechanism that moves at the top of the particular scope the variable and function declarations, before they are being executed. That means, that all declarations in a scope, are processed first, before the code is being executed. In your mental model, you can think of this process, as, if all declarations have moved to the top of your code. In other words, the Compiler and the Javascript Engine, interpret the above code, as, if it was written this way

function showInConsole() {
    const a = 5;
    console.log(a);
};

showInConsole();

There is a subtlety we need to mention here. What is happening when we have function expressions? Consider the following snippet,

functionExpression();

let functionExpression = function showInConsole() {
    const a = 5;
    console.log(a);
};

The output we get in the console is a ReferenceError: functionExpression is not defined message. A RefferenceError in Javascript, is produced when we tried to access an undeclared variable. Thus, we see that we try to assign to functionExpression a function, that is has not being declared yet. Therefore, we can conclude that function declarations are hoisted over variable declarations but not over variable assignments. That is a rule we must always keep in mind when we deal with hoisting. The same rule applies to Arrow functions, which, after all, are a variable assignment.

A worth mentioning note. After ES6 was introduced, the var statement has been shadowed (or maybe replaced), by the let and const statements. During the ES5 and before era, you could also hoist variables using var. But let and const don’t let you do that anymore, or do they? Many developers argue about if this is true or not. Some state that variables declared with let and const, are indeed hoisted but not initialized, while others state that they are not hoisted at all. My personal opinion is you should not try to pick a side on this argument and leave your head free of confusion. You should stick and wrap your head around hoisting functions, since this may make debugging a lot easier, and mostly help you understand how Javascript really works.


Profile picture

Personal blog by  Alexandros Lagkonas.
Documenting my development journey along with concepts that I find striking.