DEV Community

Steven Dawn
Steven Dawn

Posted on

Intro to Hoisting in JavaScript

Hoisting Meme

When learning to program in JavaScript you were told by instructors, mentors, or a random person on StackOverflow that you want to avoid hoisting issues in your code by using const or let.

But you ask yourself, what the heck is hoisting and why do I need to avoid it? Well, this is the right place to be!

Hoisting is when the JavaScript engine moves variables and function declarations to the top of their respective scope before code execution.

Example of Hoisting variable declaration:

x = 6
var x;
console.log(x) 
// x would be equal to 6 with no errors thrown
Enter fullscreen mode Exit fullscreen mode

Naturally, you would think this code would not work because you can't assign a variable and then have the declaration below that right?

Well, you could do just that with var because it will initialize variables before declaration, allowing JavaScript to hoist it to the top of the function and not throw any errors.

Example of Hoisting in function declaration:

dogBreed('Miniature Schnauzer')

function dogBreed(name) {
  console.log('My favorite dog breed is the ' + name + '!') 
}
// My favorite dog breed is the Miniature Schnauzer!
Enter fullscreen mode Exit fullscreen mode

Although this code runs just fine, it is best practice to avoid invoking functions before declaring them for readability.

Mixing these two together can lead to very confusing code. Take this code snippet for example:

var dogBreed = "Pug";
var favDogBreed = function () {
  console.log("My favorite dog breed: " + dogBreed);
    var dogBreed = "Shih Tzu";
      console.log("Bob's favorite dog breed: " + dogBreed);
};

favDogBreed();
// Original favorite dog: undefined
// New favorite dog: Shih Tzu 
Enter fullscreen mode Exit fullscreen mode

Confusingly enough, JavaScript initialized the first dogBreed to undefined because of hoisting and then starts executing the function which is why we got this result.

Variables that are initialized in JavaScript are not hoisted though. Interestingly enough, the code snippet below prints out NaN:

console.log(x + y)
var x = 4
var y = 2
// Output is NaN
Enter fullscreen mode Exit fullscreen mode

This happens because JavaScript is hoisting x and y but not their respective initializations = 4 and = 2 resulting in NaN because x and y are not numbers!

Thankfully in 2015, we got the ES6 revision of JavaScript and that introduced let and const which effectively outdates var.

Lets take another look favDogBreed but declare everything with let instead of var:

let dogBreed = "Pug";
let favDogBreed = function () {
  console.log("My favorite dog breed: " + dogBreed);
    let dogBreed = "Shih Tzu";
      console.log("Bob's favorite dog breed: " + dogBreed);
};

favDogBreed();
// This will throw a ReferenceError and not let this code run
Enter fullscreen mode Exit fullscreen mode

All is now right in the world and the engineer will have to go and fix their confusing code.

However just because errors are thrown now, does not mean that hoisting is patched out of Javascript. It still occurs with variables declared with let and const but they are never initialized. Take this code snippet for example:

dogName = "Sparky";
const dogName
console.log(dogName)
// This code doesn't run

dogName = "Sparky";
let dogName
console.log(dogName)
// This results in a ReferenceError
Enter fullscreen mode Exit fullscreen mode

What does this mean? For starters, hoisting is still happening with these variables declared with let and const but there are some differences.

const refuses run because of syntax error. Same thing happening with let, but JavaScript sees the variable and is aware of it, but JavaScript cannot use the variable until it has been properly declared.

When declared with let, our variable dogName is in this phenomenon called the temporal deadzone which yes, would be the sickest name for a band but is what a variable declared with let or const is in until JavaScript reaches and executes the line where the variable is declared.

The temporal deadzone does not apply to var because JavaScript initializes the variable to undefined when it is accessed before the declaration.

The best practices to avoid hoisting issues is to:

  • Declare variables and functions let and const where ever you can

  • Always declare variables at the beginning of each and every scope because this is how JavaScript and developers read code

  • Never ever use var

Congratulations! You now have a better idea of hoisting and how it works in JavaScript ES6. This (often overlooked) concept confuses developers both new and veterans alike and you have an edge in both understanding and avoiding hoisting related bugs in JavaScript!

Here are some additional resources on the topic:
W3Schools
MDN
JavaScript Docs

Top comments (1)

Collapse
 
andrewbaisden profile image
Andrew Baisden

You explained the concept well here.