Demystifying JavaScript Execution: A Layman's Guide

Have you ever wondered what exactly happens when you hit that "Run" button in your JavaScript program?
Let's take a journey through the intricacies of JavaScript execution and uncover the magic that takes place behind the scenes.
The Script: A Story in Code
function calculateSum(a, b) {
let result = a + b;
function multiplyByTwo(num) {
return num * 2;
}
let doubleResult = multiplyByTwo(result);
return doubleResult;
}
let finalResult = calculateSum(3, 5);
Act 1: Setting the Stage - Global Execution Context
When we run the above code a global execution context is created.
The execution context is created in two phases.
1st phase is the memory creation phase.
2nd phase is the code execution phase.
Memory Creation Phase
With the above code, in the first phase, javascript will allocate memory to all the variables and functions.
The
calculateSumfunction takes its place in the memory spotlight. In case of functions, it will store the entire function code in the memory space.finalResultis allocated memory with the valueundefinedin the first phase.In the bottom of the stack we have our global execution context that means, whenever any JS program is run, this call stack is populated with this Global execution context. This whole execution context is pushed inside this stack.

Code Execution Phase
Now javascript once again runs through the whole javascript code line by line.
From line 1 to 11, there is nothing to execute
The
calculateSumfunction steps into the spotlight. Functions are like mini programs. When a function in invoked a new execution context gets created.On line 13, a new execution context gets created with two components. Now, again we will go through two phases which are memory allocation and code execution.
This execution context is only restricted with function code which is from line 1 to 11.
Whenever a function is invoked, or a new execution context is created, that new execution context is put inside the stack which is
EC1here.

Act 2: Drama within Functions
Memory Creation Phase (calculateSum Execution Context)
Now we dive into a subplot:
Memory allocates space for
a,b,resultanddoubleResultasundefined.The inner function
multiplyByTwois also added in the memory with the entire function code.
Code Execution Phase (calculateSum Execution Context)
The plot thickens:
resultreceives its value as8.The inner function
multiplyByTwois encountered.

Intermission: A Quick Side Story
Memory Creation Phase (multiplyByTwo Execution Context)
Memory allocates for the parameter
numasundefined.As a new function was invoked, a new execution context gets created i.e.
EC2.

Code Execution Phase (multiplyByTwo Execution Context)
The parameter
numgets its value.The multiplication performance begins.
the
return num *2tells the function that it is done with the work and just return the control back to the local execution context ofcalculateSum()where the function was invoked.When it will encounter the
return num * 2statement, it finds the value ofnumin the local memory, performs the calculation and the control goes to the execution context ofcalculateSum()where it will replaceundefinedofdoubleResultwith16.Once the whole function code is executed, the execution context for the instance of that function will be deleted.
Then,
EC2is popped out of the stack, and the control goes back to the execution context ofEC1.


Back to the Previous Act: Resuming calculateSum
The stories intertwine:
Next, the statement
return doubleResultwill again, return the control back to the global execution context where the function was invoked.The
finalResultwill now the get its value fromdoubleResult.Once the whole function was executed, then
EC1will also move out of stack, and the control goes back to Global Execution Context (GEC).

The Finale
Now, as the entire code is done with its executions, the entire global executed context is also deleted.
As this whole program is executed, the call stack gets empty. The GEC is also popped out from this call stack and we are done with our JavaScript program. So that is how the whole code inside the JS Engine is executed.

The entire flow:

The Harmony of the Call Stack
JavaScript maintains a call stack to manage the order of execution contexts.
The global execution context starts at the bottom of the stack.
Function invocations push new execution contexts onto the stack.
After execution, contexts pop off the stack.
This dance continues until the program concludes, leaving an empty call stack.
Let's take an example to understand:
function outer() {
var outerVar = "I am outer!";
function inner() {
var innerVar = "I am inner!";
console.log(outerVar); // Output: I am outer!
}
inner();
console.log(innerVar); // Error: innerVar is not defined
}
outer();
Code Flow in terms of Execution Context and Callstack:
Global Execution Context (GEC):
Memory Phase:
outer: <function code>
Call Stack: [GEC]
Execution of Function
outer():Local Execution Context for
outer:Memory Phase:
outerVar: undefined
Call Stack: [GEC, outer()]
Execution of Function
outer()(Continued):Memory Phase (Contd.):
outerVar: "I am outer!"
Execution Phase:
- Call to
inner()pushes a new local Execution Context forinneronto the Call Stack.
- Call to
Call Stack: [GEC, outer(), inner()]
Execution of Function
inner():Local Execution Context for
inner:Memory Phase:
innerVar: undefined
Execution Phase:
Memory for
outerVaris accessible within the scope ofinner.console.log(outerVar)printsI am outer!.
Removal of
inner()from Call Stack.
Call Stack: [GEC, outer()]
Back to
outer()Execution:Execution continues after the call to
inner().Attempting to print
innerVarin the console results in an Error sinceinnerVaris not accessible outside its scope.Removal of
outer()from Call Stack.
Call Stack: [GEC]
Program Conclusion:
GEC is deleted.
Call Stack is empty.
Key Takeaways
JavaScript execution starts with the creation of a global execution context.
Execution contexts consist of a Memory Component and a Code Component.
The Memory Creation and Code Execution phases manage variable and function allocation.
Function invocations create new execution contexts.
The call stack determines the sequence of execution contexts.
Now, the next time you run your JavaScript code, visualize the dance of execution contexts and the orderly steps taken by the call stack.
Happy coding!




