JavaScript Hoisting

A few weeks ago, Dev Bootcamp NYC was hosting lightening talks given by alumni. Knowing the audience was going to be mainly current students, as well as people considering DBC, I wanted to talk about something that tripped me up when I first started learning web development and felt the concept of hoisting in JavaScript would be perfect. It is a concept that is relatively easy to grasp, yet seems to be elusive to students when they are first learning JS.

What is hoisting?

When looking at a file of code it may seem like the computer will read the code line by line, top to bottom. While this is sometimes true (for simplier applications) there are instances where the computer will read certain things first.

For example:

console.log(a); // ReferenceError

Here we are trying to print a variable a that has not yet been defined.

var a = 2;

console.log(a); // 2

Setting the variable a to 2 will now print 2 to the console as expected.

However if you move the var a = 2 declaration below the console.log you would get:

console.log(a); // undefined

var a = 2;

Undefined? Why is this happening? Why isn’t the console.log spitting out a ReferenceError since a is not defined before the variable is printed?

This is hoisting in JavaScript!

When the computer goes to execute this file it hoists all variable declarations to the top of the file but does not assign them a value. So the code we have above is actually read by the computer as:

var a;

console.log(a); // undefined

a = 2;

It is not only variables that get hoisted to the top when the computer executes the code, but function declarations as well.

Consider:

foo(); // 'Hello World!'

function foo() {
  
  console.log('Hello World!');

}

The function declaration foo is getting hoisted to the top when the computer runs the code. So what the code above looks like to the computer is:

function foo() {
  
  console.log('Hello World!');

}

foo(); // 'Hello World!'

Keep in mind however that function expressions are not hoisted as function declarations are.

So foo here would not be hoisted:

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

var foo = function() {
  
  console.log('Hello World!');

}

Again the computer is actually interpreting the code as:

var foo;

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

foo = function() {
  
  console.log('Hello World!');

}

One thing to keep in mind is that variables and functions are hoisted to the scope they belong in. In addition, assignments and executables are left in place.

For example:

foo(); // undefined

function foo() {

  console.log(a);

  var a = 'Hello World!';

}

The concept of hoisting is extremely important in understanding how the computer reads our JavaScript files and when variables and functions will be set and defined in the scope.

If you would like to continue digging into hoisting in more detail an excellent resource is Kyle Simpson’s book, You Don’t Know JS: Scopes & Closures. Specifically, in Chapter 4 he goes in depth with JavaScript hoisting and it is a great way to dig deeper into this concept.