Hoisting in JavaScript
How Hoisting Works in JavaScript — Variables and Functions
What is Hoisting in JavaScript?🤔
Hoisting is a very important process in JavaScript that’s made by the interpreter. The interpreter moves
the declaration of functions and variables to the top of their scope, prior to the execution of the code
. This feature is known as hoisting
in JavaScript.
Variable Hoisting
In JavaScript, we can declare variables with const, let, and var. I will explain in detail each variable declaration type individually because the behavior is not the same when hosting.
var hoisting 🧐
Let’s look at some 😉examples to understand hoisting in the case of var variables.
console.log(a); // outputs 'undefined'
var a = 3;
We expected 3 but instead got undefined. Why?
Remember JavaScript only hoists declarations, not initializations. That is, during compile time, JavaScript only stores function and variable declarations in the memory, not their assignments (value).
But why undefined?
🧐
When the JavaScript engine finds a var variable
declaration during the compile phase, it will add that variable to the lexical environment
and initialize it with undefined
, and later during the execution when it reaches the line where the actual assignment is done in the code, it will assign that value to the variable.
So the initial lexical environment for the above code will look something like this:
lexicalEnvironment = {
a: undefined
}
That’s why we got undefined
instead of 3
. And when the engine reaches the line (during execution) where the actual assignment is done, it will update the value of the variable in its lexical environment. So the lexical environment after the assignment will look like this:
lexicalEnvironment = {
a: 3
}
Why it’s helpful?🥸
It’s helpful because we will not receive the error of
Uncaught ReferenceError: a is not defined,
and instead of it, we will receive undefined as the returned value.
What are the differences?🥸
When we receive the error of
Uncaught ReferenceError: a is not defined
, it means that the variablea
is never declared, and when we receive a return value of undefined, it means that the variable is declared but not initialized or assigned to the value3
as it happens somewhere in the code; instead, the hoisting process initialized thea
variable to the default value undefined.
Const & Let Hoisting💥
So are let and const variables not hoisted?🤫
The answer is a bit more complicated than that. All declarations (function, var, let, const and class) are hoisted in JavaScript, while the var
declarations are initialized with undefined
, but let and const declarations remain uninitialized.
Here come the big differences between var and const/let hoisting. Behind the scenes, variables that are declared with let and const
are also hoisted, but unlike var, they do not receive the default value of undefined
.
So what happens if we call const/let variables before they are initialized?🤔 We will get an error: Uncaught ReferenceError: can’t access lexical declaration ‘myName’ before initialization.
console.log(myName); // Uncaught ReferenceError: can’t access...
function message(){
console.log("Hello World!");
}
const myName="chhakuli zingare";
Function Hosting😯
This type of hosting is very important and really makes our code safer. Let’s illustrate it by an example.
message(); //Will print to the console "Hello World".
function message(){
console.log("Hello World");
}
As we can see in the example above, we call a function that’s not yet declared, but still, it will work absolutely fine. That’s because ‘function hosting’
is involved. Behind the scenes, the declaration of the function message
is moved to the top of the JavaScript file. This means that actually, the function call is made after the declaration and not before it.
This magic protects our code from wrong calls that may be made before the function declaration.
Arrow Function Hosting 🏹
The hosting behavior of arrow functions
and regular functions are not the same. Let’s take a look at the example below:
message(); //Uncaught TypeError: printSomething is not a function.
var message=> (){
console.log("Hello World");
}
Why does that happen?
The hosting behavior of arrow functions are like the keywords const, var, let
and when we try to call the message
function, we receive the error Uncaught TypeError: message is not a function
. Let’s think about the steps behind the scenes:
- The message is a var variable, so because of that, it goes to the top of the JavaScript file.
- The variable message received the default value of undefined.
- We try to call the arrow function message, but it’s still defined with the value of undefined.
- The error Uncaught TypeError: message is not a function occurs.
Conclusion🙆♀️
So now we know that during hoisting
our code is not physically moved by the JavaScript engine. Having a proper understanding of the hoisting mechanism
will help you avoid any future bugs and confusion arising due to hoisting.
To avoid possible side effects of hoisting like undefined
variables or reference error
, always try to declare the variables at the top of their respective scopes and also always try to initialize variables when you declare them.