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
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!
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
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
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
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
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
andconst
where ever you canAlways 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)
You explained the concept well here.