Blog _

Javascript Hoisting – Demistified


Posted at 8:21 pm on February 6, 2018 by Cesar

Hello gang,

This week we are going to look at memory hoisting in Javascript. I will include
a few simple examples which should help demonstrate hoisting in action that will help clarify the compiler behaviour and help you avoid writing code that may lead to unexpected bugs. The aim here, as always, is to keep things as simple as possible.

lets begin!

What is hoisting?
A clue is in the word “hoisting”.

To “hoist” is to raise or haul something up (usually with pulleys and ropes). In Javascript, hoisting is the term used to describe the way that the Javascript engine’s parser “hoists” variable and function declarations.

It seems fairly obvious that when we run our Javascript code, the parser will interpret it from top to bottom line by line but this is not strictly true. It will actually scan the code for declarations and hoist them before proceeding to synchronously interpret code. This can be easily demonstrated by running a function before it is declared.

sayHello();

function sayHello(){
    console.log('Hi!');
}

The code above will run without an error despite the fact that we are making a call to the function before it is even declared. Hence, we can say that all function declarations are hoisted, and will behave as if they were declared at the top of our code – even if they weren’t.

We also see the same behaviour with variable declarations. Let’s start by making the distinction between a declaration and an assignment.

lets create a variable in Javascript:

var name = 'John';

Here we have combined a two step process into one – the declaration and the assignment . We could have just as easily have done the following:

var name;
name = 'John';

The reason I bring this up is because the parser will hoist variable declaration but not the assignment. This can lead to some unexpected results when the code is run.

console.log(name1 + ' ' + name2 + ' ' + name3 + ' ' + name4);
var name1 = 'John';
var name2 = 'Paul';
var name3 = 'Ringo';
var name4 = 'George';

When running the code above, it would seem natural to expect a ReferenceError message as we are trying to reference variables that have not been defined until after the console.log() command. Instead, what we get outputted to the console is:

"undefined undefined undefined undefined"

This is because the variable declarations have been hoisted by the parser but have they have yet to be assigned a value and therefore return “undefined” to the console.

Think of the code above as behaving as follows:

var name1, name2, name3, name4;
console.log(name1 + ' ' + name2 + ' ' + name3 + ' ' + name4);
name1 = 'John';
name2 = 'Paul';
name3 = 'Ringo';
name4 = 'George';

Note that it is the declarations of the variable that are hoisted and not the assignments.

Now let’s consider the following code:

var name1 = 'John';
var name2 = 'Paul';
console.log(name1 + name2 + name3 + name4);
var name3 = 'Ringo';
var name4 = 'George';

This will output the following to the console:

"John Paul undefined undefined"

Here we can see that all the variables are declared, but the assignments are made to the first two variables and not the last two as you would expect.

What happens when using function expressions? how are hoisted?

thisExpression(); // TypeError: thisExpression is not a function

var thisExpression = function (){
    console.log('Hello!');
}

Unlike function declarations, function expressions are NOT hoisted. When the code above is run, the console will return TypeError: thisExpression is not a function. The parser sees var thisExpression as a variable declaration and hoists it, treating it as a normal variable declaration, but then throws an error when it sees it being attempted to be run as a function.

If your variables are unexpectedly returning “undefined”, it could be because of hoisting. It is a good idea to make sure that you declare and initialise your variables with values before you use them!

You could also enable “strict mode” which will throw a ReferenceError any time you attempt to use a variable before it is declared. This is done by simply adding "use strict"; to the top of your Javascript file:

"use strict";
//the rest of your JS code...

…And remember, function epressions are not hoisted!

Here are a some more examples of hoisting from Mozilla

I hope you found this helpful. I wanted to keep this as short as possible but at the same time deliver as much value as possible – if you did not understand anything, let me know and I will elaborate further.
Thanks for reading!
Cesar



Comments

Write a Reply or Comment

Your email address will not be published. Required fields are marked *