11 min read
Well by the end of this blog you will have a clear understanding of that by knowing two important concepts that make it possible
- Execution Context
- Call Stack
1. Execution Context
Before diving deep into the working of
Execution Context can be thought of as an imaginary box where all the storage as well as code execution happens.
Execution Context(EC) can be classified into two main types:
- Global Execution Context(GEC)
- Functional Execution Context(FEC)
I will specify during further explaination that which type of
Execution Context is being created at that moment, other than that we will refer to it commonly as
Execution Context is divided into 2 parts
- Memory Component
- Code Component
The Memory Component also known as the Variable Environment allocates memory and stores variables and functions as key: value pairs.
Now if I may present the
Execution Context visually as a diagram it can be shown as:
So coming back to
Let's understand the working in more detail with the help of a code example.
Now when we run this code, a
Global Execution Context(GEC) is created
Execution Context is created in two phases.
- Memory Creation Phase
- Code Execution Phase
The JS Engine goes through the code line by line. It encounters variable declaration at line 1 and allocates memory to the variable
n. Then it goes to line 2 and allocates memory for a function named
In the case of variable
n, a special value
undefined is stored with it whereas the whole function code is stored as it is in the case of the function.
Coming to line 6 and 7 it encounters two more variables
square4 and as they are variables assigns their value as
After completion of Memory Creation Phase the
Execution Context might look like this
Now the second phase i.e Code Execution Phase begins
The JS Engine again goes through the code line by line and executes the code.
It executes the first line
var n = 2 and replaces the
undefined value of
n from the Memory block with the actual value
Then it comes to line 2 and encounters a function
square and skips the code from line 2 to line 5.
Then when it goes to line 6 and encounters a function call or a function invocation. Now it knows that it has to execute a function.
Whenever a function is invoked a new
Execution Context will be created and this will be a brand new
Functional Execution Context(FEC) inside the
Global Execution Context(GEC)
Execution Context will again consist of two blocks, Memory and Code, and will also follow the two phases of creation.
In its Memory Creation phase, it will allocate memory to variables and functions used in its execution.
It scans for variables and it finds
num as a parameter and
ans in the body and assigns
undefined to them.
In the Code Execution phase the value of
n which is 2 is passed to
Now in the function body, it executes
num * num and the evaluated value is replaced for
ans inside the
After execution of line 3, it encounters a
return keyword on line 4, so the function knows its execution is finished and now it's time to return the control back to the
Execution Context from where it was invoked which is the
While returning it returns the value of
ans from its
Execution Context to the Global one so the value of
square2 is changed from
Functional Execution Context is deleted after the return of control.
A visual representation of the whole process discussed:
Now the control moves to line 7, where it finds another function invocation
square(4) with value 4 as an argument. Again brand new
FEC will be created. The whole procedure used to invoke
square(n) as explained above will be repeated. The value will be evaluated and returned into square4.
If there is a function inside a function. Then a nested
FEC will be created inside the
FEC which is inside the
GEC. This has no end it can go beyond and beyond.
After the execution of the whole program is finished, The
Global Execution Context also gets deleted.
Phew, that was all about the "Execution Context", now you know how is it created and how it executes the code.
Remember I said all this nested
The Call Stack, let's learn more about it in detail.
2. Call Stack
You must be familiar with the stack data structure. If not, please read it here
So as we know Stack is a LIFO(Last in First Out) Data Structure.
To enter data in the stack we use
push and to delete we use the
The same is the working of the Call Stack in JS.
So for better understanding let us see a diagram of the working of Call Stack for the mini-program we saw earlier along with
Initially the Call Stack is empty.
Global Execution Context is at the bottom of Call Stack. Whenever a program is run, the Call Stack is populated with the
Whenever a new function is invoked a new
FEC is created and pushed into the stack. Only when it is finished executing, It is popped out of the stack.
At the end, the
GEC is also popped off and the Call Stack becomes empty.
This Call Stack is used to manage all these
Call Stack maintains the order of execution of
Link to the videos which I followed to write this blog.
That's all from my side. How was it? Let me know in the comments.
If you really liked it then do share it with your friends or colleagues.
Have any doubt or want to work on a project together then follow me on Twitter and message me there. Also, comment on what should be the next topic and I will try to make that possible.