Let's Understand JavaScript is a series of blogs explaining JS in the simplest way possible, demystifying the jargon on your way.
Hoisting
Before learning hoisting in the right way it's important to unlearn the wrong stuff that's popular around the web. It's not true that variables and functions are moved to the top of the scope before the execution. Let's understand this in a better way!
Hoisting is a mechanism by which you can access variables and functions in JS even before they are initialized with any value.
var printName="JavaScript";
function print(){
console.log("Learning JavaScript");
}
console.log(printName);
print();
console.log(print);
The output of this code is
JavaScript
Learning JavaScript
function print(){
console.log("Learning JavaScript");
}
It works well and good. So, let's see what happens when we jumble our code.
console.log(printName);
print();
console.log(print);
var printName="JavaScript";
function print(){
console.log("Learning JavaScript");
}
The output for above is:
undefined
Learning JavaScript
function print(){
console.log("Learning JavaScript");
}
So as you see, JS prints undefined
for the variable declared with var but not an error.
Similarly, the function call prints the actual value and when we try to console the function, it prints the whole function itself.
Not to forget all these happens before the actual variable/function is initialized.
JS behaves this way because whenever you run a piece of code the execution happens in two phases, in the first phase the variables are allocated memory and initialized with an undefined
keyword while the functions are allocated memory and the memory space holds the entire function code as shown in the pic above. And that's the reason behind hoisting!
I highly suggest you read the first blog of this series which explains the creation of execution context to understand hoisting better.
Not defined vars
console.log(something);
var name="JavaScript";
When you try to access a variable that is not defined anywhere in your code in that case, you would end up in the following error because JS checks for that variable in the memory and it wouldn't find that variable.
not defined !== undefined
ReferenceError: something is not defined
Function Declaration with arrow function/ function expression:
A function declaration can be made in 3 different ways: 1) Regular function 2) Arrow function 3) Function expression -> We can assign a function to a variable in JS
console.log(welcome);
welcome();
console.log(welcome2);
welcome2();
welcome();
function welcome(){
console.log("Helloo");
}
var welcome2 = () => {
console.log("Helloo from welcome2");
}
var welcome3 = function (){
console.log("Helloo from welcome3");
}
When you try to access the arrow function/function expression similar to a normal function, you would end up in an error because JS considers them as variables and assigns undefined
to the function during the memory allocation phase.
TypeError: welcome2 is not a function
Let and Const Hoist:
Now, it's time to demystify another truth. What if I say Let and const are hoisted.
Yeah, that's true they are hoisted. Let's see how.
let a =10;
const b=20;
function numLogger(){
console.log(`a= ${a}, b= ${b}`);
}
numLogger();
So, let and const
are not hoisted in global scope but under a reserved space for them which is script here.
So, these variables can be accessed only after their initialization unlike the var
declared variable,
they are not initialized with default value undefined
.As they tend to be in Temporal Dead Zone before they are initialized.
Temporal Dead Zone(TDZ):
TDZ is the phase between which the let/const variables are declared(i.e created) and it is initialized with some value. So, for const
TDZ becomes zero as we have to initialize it with some value at the time of creation.
Until the line in which they are initialized is executed, accessing them before initialization results in the following error.
Summary:
Hoisting is a mechanism by which the compiler allocates memory for variable and function declarations before the execution of the code. Hence you can access those variables and functions even before their initialization.
Arrow functions and function expressions will be treated as variables and be assigned with undefined
before they are actually executed.
Some variable is not defined
is not same as undefined
Let and const variables are also hoisted but unlike for var
, the variables are not initialized with a default value of undefined. They can be accessed only after the line in which they are initialized is executed
Yeah, that's all about hoisting !!