Javascript Hoisting, Memory Allocation & Scopes.
Have you ever been to an exam hall? Seats allotted in an exam hall is something similar to how JavaScript allocates memory to its variables.
Hahaha!! Apologies if I confused you more, let’s go through with this article and you’ll surely get what I meant to say.
What is Javascript?
Javascript is a single-threaded, non-blocking, High-level programming language. It used to be available for browser programming, where each browser had its own Javascript engine to execute a Javascript file. A fun fact about JavaScript is that every concept you learn often leads to a deeper, more advanced topic.
JavaScript code execution happens in two phases:
Phase 1: Memory Allocation or Hoisting — In this phase, the Javascript engine scans the Javascript file and allots some memory to the variables.
If you look at the image below, you’ll find how the code execution had not even started, as we stopped the code at line 1 but still, javascript had already scanned through the file and allotted memory in local stack.
But wait, that’s not enough. There’s a lot to know about hoisting. Without learning about scopes and hoisting concepts, you’ll live in confusion about why your code gives unexpected errors.
Phase 2: Code execution or Execution context — In this phase, the Javascript engine executes code line by line. It is a concept in which we learn about how Javascript handles complex, blocking codes smoothly and also keeps track of it. We can talk about this phase in another article.
We are gonna cover phase 1 in this article while phase 2 demands its own article for better understanding.
What is Hoisting?
Hoisting is JavaScript’s behavior of moving declarations of variables, functions, and classes to the top of their scope before executing the code. However, only var is initialized with undefined, while let, const, and classes remain in the Temporal Dead Zone (TDZ) until their actual declaration.
What is Scope and Temporal Dead Zone?
var a; //Declaration - Variable is only declared, automatically initalize with undefined
a = "Hello world"; // Initialization - Variable is initialized with a value
var b = "Hello world" // Assignment - Declaration and initialization together.If you are a bit aware of Javascript, so you might know that Javascript uses three keywords to declare a variable.
- var
- let
- const
var — var is the oldest keyword in Javascript but also it is a non-recommended keyword to declare a variable. Let’s see why..
- When a var is declared, it’s initialized with the undefined value. So if a var variable is accessed before the initialization, it returns undefined.
- var is function-scoped, meaning it's accessible anywhere inside the function where it's declared. However, it ignores block scope (inside if, for, etc.), which can lead to unexpected variable overwrites.
- A var can be redeclared and reassigned.
function example(){
var a = 10; //Assigned variable a with value 10
if(true){
var a = 20; //Re-assigned variable a with value 20
}
console.log(a) //Now the value of a is updated with 20
}
example()let and const —Due to these issues, JavaScript introduced let and const in ES6. Among them, const is the most recommended as it prevents reassignment, while let is preferable when reassignment is needed..
- let and const a block-scoped, meaning they are accessible only within the {} block where they are declared.
- A block is a group of code covered inside of pair of curly braces to expect multiple lines.
- If let and const variables are called before their initialization, so it throws a Reference Error.
- The only difference between let and const is, that let cannot be redeclared but can be re-assigned whereas const cannot be redeclared nor re-assigned. const is like the final keyword, whose value cannot be modified in the future.
- const variable must but assigned once, if it's re-assigned it throws TypeError. It cannot be declared and initialized separately, it must be assigned directly else it will throw a syntax error.
So here, we got to know that var is a function-scoped variable while let and const is a block-scoped variable. While var is allocated in memory with an undefined value, let and const get into the Temporal Dead Zone. But!!!! What’s a Temporal Dead Zone?
Get Mayank singhal’s stories in your inbox
Join Medium for free to get updates from this writer.
Variables declared with let and const are hoisted to the top of their scope, but they are not initialized until their declaration line is reached. This means they cannot be accessed before their declaration, and attempting to do so results in a Reference Error. The period between entering the scope and the actual initialization of a variable is known as the Temporal Dead Zone
Amazing to see you till here. So till now we have covered General Hoisting concepts like scope, Temporal dead zone and different variables scopes. Now, let’s have some fun with functions and classes.
Hoisting in functions and classes
Let’s learn some basic keywords we are gonna use in this section and keep on exploring their role in hoisting:
Function Declaration AKA Function Statement — It is a regular function used to be written in any programming language.
- What you’ll observe in the below image is that a regular function is also hoisted, BUT it’s not returning undefined or throwing Reference Error. It’s actually executing that function because Javascript hoists the function and initializes with the actual function. This you may not find in any other programming language. This is also known as fully hoisting.
Function expression — When a function is assigned to a variable, and that variable is called to execute that function. That style of writing a function is known as a function expression.
- Now, you cannot directly execute the function with its name but you’ll have to use the variable to execute the function.
- Are you wondering, why this function is not fully hoisted? So the clear understanding over here is, that now the function is assigned to the variable, it will always be hoisted as a variable. So as a let variable gets into Temporal Dead Zone before the initialization, similarly this function gets into the Temporal dead zone till the variable “a” is initialized.
/**
* Function Declaration
*/
example2(); // ✅ Works: "Hello World!"
function example2() {
console.log("Hello World!");
}/**
* Function Expression
*/
example() //❌ReferenceError: example is not defined
a() //❌ReferenceError: Cannot access 'a' before initialization
let a = function example(){
console.log("Hello world")
}
a() //✅ Output: Hello world
example() //❌ReferenceError: example is not defined- Similar to function, classes are also allocated to memory but get into the Temporal Dead zone before their actual initialization.
/**
* Class Hoisting
*/
const obj = new MyClass(); // ❌ ReferenceError
class MyClass {
constructor() {
console.log("Hello!");
}
}As we are getting closer to the end of the article, let’s just re-understand the exam hall example that I used at the beginning of the article.
Before you enter the examination hall, the Examination team(JS engine in our case) goes through the candidates' list and each candidate is assigned a seat before even the candidate appears for the exam. Similarly, the Javascript engine scans through the code and allocates memory to each variable, function, and class before its execution.
Conclusion
Understanding hoisting, memory allocation, and scopes in JavaScript is crucial for writing efficient and bug-free code. We’ve seen how JavaScript allocates memory before execution, and how var, let, and const behave differently due to their scope and hoisting characteristics.
The key takeaway is that using let and const is generally recommended over var to avoid issues related to unexpected re-declarations, re-assignments, and the lack of block scoping. Additionally, knowing about the Temporal Dead Zone (TDZ) helps prevent errors when dealing with let and const.
By mastering these concepts, you’ll gain better control over JavaScript’s execution flow, leading to more predictable and maintainable code.






