Execution Context In Javascript

Photo by RetroSupply on Unsplash

Execution Context In Javascript

Table of contents

No heading

No headings in the article.

In JavaScript, when a program is executed, a new execution context is created. This context has two components: a VARIABLE ENVIRONMENT (where memory is allocated for variables and functions) and a THREAD OF EXECUTION (where code is executed).

The first step in the execution process is memory allocation. When a variable is declared, it is assigned a placeholder value of undefined until its value is assigned during code execution. When a function is declared, the entire function code is stored in memory.

For example, let's consider the following code:

var n = 2;

function square(num){
  let ans = num*num;
  return ans;
}

var square2 = square(n);
var square4 = square(4);

As soon as a JavaScript program starts executing, a new execution context is created. This new execution context has two parts: the variable environment (where memory is created), and the thread of execution (where code is executed).

First, the program assigns memory to the variables and functions. In the case of variables, during the memory creation phase, they are assigned a value of undefined. In the case of functions, during the memory creation phase, the entire function code is stored.

In our example, the memory creation phase will first assign memory to the variable n, and then to the function square.

n : undefined
square : function square(num){
  let ans = num*num;
  return ans;
}

Once the memory creation phase is complete, JavaScript starts executing the code line by line.

In the first line of code, we have the value n = 2. The value of n is assigned in the memory creation phase. At this point, n is assigned a placeholder value of undefined. During code execution, n is assigned its actual value of 2.

In the case of the function, we need to understand function declaration and function invocation.

Function declaration occurs between lines 4 to 6, where we simply declare the function. In contrast, function invocation occurs in lines 9 and 10, where we are calling the function.

When a function is invoked, a new execution context is created. This new execution context has two parts: memory creation and code execution. For each function invocation, a new execution context is created.

At the time when the JavaScript program is executed, the first execution context that is created is known as the global execution context. For each function invocation, an execution context is created. The main difference between the global execution context and the function execution context is that the global execution context is created when the program starts executing, and the function execution context is created when a function is invoked.

Let's now understand the invocation of the square function:

function square(num) {
  let ans = num * num;
  return ans;
}

As soon as the the square function is invoked, an execution context for square is created, and the memory creation phase is executed. The function has a parameter num, so memory is assigned to both num and ans.

Memory creation:

{
  num: undefined,
  ans: undefined
}

During code execution, we pass the value of 2 as an argument to the function. This value is assigned to the num parameter. In the next line, we have num * num, which is 2 * 2 = 4, and this value is assigned to the ans variable.

{
  num: 2,
  ans: 4
}

Finally, we have a return statement, which tells us to end the function, and we return the value of ans. This value is received on line 9, and square2 is assigned a value of 4.

In the global execution context, n is 2, square2 is 4, and square4 is undefined.

The same process is repeated for var square4 = square(4), which creates a new execution context.

Now the same process will happen for var square4 = square(4);. It won't have any difference in the way the execution context is created. Memory creation will happen first, then code execution will occur. The same process that we have already discussed. Whether you pass the value 4 directly as an argument or you pass the value from some variable, it won't make any difference in the code execution part.
For Example

var a = 1000;
let sqrt1 = getSqrt(a);
let sqrt2 = getSqrt(1000);

Both of these invocations are not going to make any difference, so don't get confused here.

Also, as soon as the function returns the value or is done with its part, the execution context will be deleted. JavaScript handles all of these things with the use of a stack.

Now, what is the stack here again?

Whenever an execution context is created, it will be pushed onto the stack. Once it is done executing the entire function code, it will be removed from the stack, and the control goes back to the line from where we executed that function. At last, once we are done with our entire program execution, the Global Execution context will be removed from the stack as well.

One last thing to understand here is that the call stack is also known by a few names:

  • Execution context stack

  • Program stack

  • Control stack

  • Runtime stack

  • Machine stack

So don't get confused if you hear any of these names. It's still the call stack."

That's all about execution context and call stack. And thanks to Akshay Saini
for creating an incredible Namaste Javascript playlist this blog is just whatever learning I had from there.