How JavaScript works behind the scene - Execution Context and Call Stack
Tags: javascript, webdev, programming, tutorial
Published: 2021-11-18 07:15:08

Hello World!

JavaScript is the most hated as well as the most loved programming language in the world. And the reason for the hate is that most people don't understand the underlying beauty of it.

So, In this post we will see how functions are executed in JavaScript, and how variables are defined and initialized.

We will also discuss, what is hoisting?

## Execution Context
Any function in JavaScript is executed in two phases:

1. **Declaration Phase**: This phase is only responsible for declaring variables and functions.
2. **Execution Phase**: This phase is responsible for executing function blocks.

Let's understand both phases one by one.

We will use the following snippet to understand the execution context.

```js
var x = 42;
var y = 21;

function add(a, b) {
  return a + b;
}

function multiply(a, b) {
  retrn a * b;
}

let sum = add(42, 21); // 68
const product = multiply(24, 20); // 480
var sumProduct = multiply(add(x, y), 0);

console.log(sum, product, sumProduct);
```

Note: In the above snippet some variables are defined with **var**, some with **let**, and some with **const**. I did that on purpose to show how each of them works differently in execution context.

## Declaration Phase
In declaration phase variables and functions are allocated memory. But there is a slight difference in where the memory is allocated to var and let, const.

- **var**: var is allocated memory in global scope or in it's function scope and is initialized with *```undefined```*.

- **let and const**: let and const are allocated memory in TDZ (Temporal Dead Zone), hence is not accessible or defined while the variable is in TDZ. It remains in TDZ unless assigned a value (initialized).

> TDZ (Temporal Dead Zone) is the time between hoisting (declaration) and value assignment (initialization).

![declaration phase](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uvmu4my9ewjr16trryjx.png)

## Execution Phase
In execution context:
- Function blocks are executed in global execution context.
- Variables are assigned values. 

If there are nested functions, then further **Function Execution Context** are created in GEC (both declaration and execution phases runs again for the nested function).

![execution phase](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qt2klzkabvzl6t3wumcr.png)

One important thing to note is that, *Once a function is returned, it is cleared / removed from the execution context*. And it is done with the **Call Stack**.

## CallStack
Execution context is maintained using a "Call Stack". A stack is a LIFO (last in first out) data structure. In a stack we only insert or delete elements at the top of stack, think in terms of JavaScript Array.push and Array.pop method.

There can be only one execution context running at a time, that's why **JavaScript is a single threaded language**.

Whenever an execution context is halted (may be due to some delay or data fetching), a different execution context becomes the current running EC. The halted EC might then at a later point pick back up where it left.

![call stack](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/51e01efmqjwhzhz17kom.png)

## Hoisting
The concept that variables are allocated memory (declared) before the execution of code is known as hoisting.

- var is accessible (with undefined as value) before it's declaration because it is declared in global memory.
- let and const are also hoisted (declared before execution) but in TDZ (temporal dead zone), hence are not accessible before their declaration in the code.

So, if the question is, Are let and const hoisted in JavaScript? The answer is **Yes, they are hoisted but in temporal dead zone**.

------------------------------------

So, that's it for this post, if you found this post helpful consider joining my [Newsletter](https://swastikyadav.com) where I share epic weekly content to build your skillset.

Thank You!