invaderWeb Dev Bit by Bit

Overview of hoisting in JavaScript

Published on July 01, 2020

When doing mock technical interviews I often ask this question: 'Can you explain what hoisting is and how it works in Javascript?'

For beginners it isn't always easy to articulate an answer. I thought I would try to write some points that might be expected when you get this question.

This is not meant to be an exhaustive blog post - I am not talking about classes for example. I am adding some great resources at the bottom if you want to dive deeper into hoisting.

Definition

Hoisting is a JavaScript mechanism where variables and function declarations are 'moved to the top' of their scope before code execution. They are not physically moved, indeed, the variable and function declarations are put into memory during the compile phase, but stay exactly where you typed them in your code.

This means that no matter where functions and variables are declared, they are 'moved to the top' of their scope regardless of whether their scope is global or local.

The hoisting mechanism only 'moves' or more accurately puts into memory during the compile phase the declaration, the assignments aren't - this is explained in more details below.

Hoisting variables

All variables defined with the var keyword have an initial value of undefined.

console.log(beHappy)
// output: undefined

var beHappy = "If you're happy and you know it, clap your hands"

In JavaScript, an undeclared variable is assigned the value undefined at execution and is also of type undefined.

JavaScript allows us to both declare and initialise our variables simultaneously, this is the most used pattern: var a = 100; but in the background JavaScript is declaring then initializing variables in several steps:

  • Declaration: var a
  • Initialisation/assignment: a = 100
  • usage: var a = 100

All variables are hoisted, variable declarations are processed before any code is executed. However, undeclared variables do not exist until code assigning them is executed. Assigning a value to an undeclared variable implicitly creates it as a global variable when the assignment is executed: all undeclared variables are global variables.

function beHappy() {
  a = "smile"
  var b = "everyday"
}

happy()

console.log(a)
// a is accessible as a global variable outside the scope of beHappy()
// output: smile

console.log(b)
// b isn't accessible outside the scope of beHappy() because it was declared
// output: ReferenceError: b is not defined

With ES6, JavaScript introduced let and const. The difference in this case is how it initialises them. Variables declared with let and const remain uninitialized.

Accessing a variable defined with let or const before its declared will yield a ReferenceError instead of undefined with var.

console.log(beHappy)
// output: ReferenceError: happy is not defined

let beHappy = "If you're happy and you know it, clap your hands"

However the following code will result in an output of undefined instead of ReferenceError:

let beHappy

console.log(happy)
// output: undefined

beHappy = "If you're happy and you know it, clap your hands"'

Hoisting functions

There are two types of functions in JavaScript: function declarations and function expressions.

Function declarations are hoisted:

hoisted() // Output: "This function has been hoisted."

function hoisted() {
  console.log("This function has been hoisted.")
}

Functions expressions are not hoisted:

expression() //Output: "TypeError: expression is not a function

var expression = function () {
  console.log("Will this work?")
}

Resources

MDN Hoisting

JavaScript Variables Hoisting in Details

JavaScript Hoisting