What is an Execution Context in JavaScript
You might have heard about hoisting, scope, scope chain, and lexical scope. These are often confusing for beginners or even for some experience developers and these are very important as they create a base for your JavaScript journey. If you don't want to keep scratching your head while you try to understand the JavaScript code you should know these topics.
But to understand these topics you should know Execution Context in JavaScript. So, buckle up! as we are going to see what this Execution Context is and why it is so important.
First Let's understand what this execution context is
In simple words, You can consider it as an environment or a container inside which JavaScript code is executed.
There are three types of Execution context:
Global Execution Context
Function Execution Context
Eval Execution Context
Note: We are not going to discuss the Eval Execution context in this blog as this is not much used by JavaScripts developers due to security concerns and performance issues.
Now let's see in detail about Global and Function Execution Context.
Global Execution Context:
Global execution context is the default execution context and it is created when the JS engine runs the code for the first time. The code that is not inside any function is in the global execution context. Global Execution context is always the first execution context to be pushed into the Call Stack and there is only one Global Execution context.
Function Execution Context:
Every time a function is invoked a completely new execution context is created for that function. Each function has its own execution context which contains variables and statements to be executed for that function. There can be multiple function execution contexts. Wherever an execution context is created it is stacked up in the Call Stack or Execution Stack.
Wait! But what is this Call Stack or Execution Stack by the way?
It is nothing but a stack data structure that is used by JS for managing the execution contexts and also controls the code execution. It follows the LIFO (Last In First Out), So the Global execution context (GEC) is always the first one to be pushed into the stack followed by the Function execution context (FEC) if any.
The active execution context is the one that is on top of the Execution stack. JS engine executes the function of the active execution context and when it is completed that execution context is popped off from the stack.
How this JS execution context is created?
The execution context is created in 2 phases.
Memory Allocation/Creation Phase.
Code Execution Phase.
Phase 1:- Memory Allocation/Creation Phase
In this phase, the JS parser goes through the JS code and allocates memory to variables and functions. The variables are not assigned any value during this phase but it is assigned a special keyword "undefined" and functions are assigned the function definition as it is. This is also known as a variable Environment.
Phase 2:- Code Execution Phase
As JS is a synchronous, single-threaded language which means it can only execute one line at a time, it runs the code line by line, and during this code execution phase, the variables which were allocated memory during the Memory allocation phase are initialised with the given value. During this phase whenever function invocation is encountered a brand new execution context is formed.
Now we have covered all the required concepts which we need to understand the Execution context.
Let's understand Execution context and call stack with the help of an example and see what exactly happens behind the scene when we run a JavaScript code.
1. var a = 20;
2. var b = 10;
3. function multiply(e, f) {
4. var g = 20;
5. return e * f * g;
6. }
7. var c = multiply(a, b);
8. console.log(c);
I have marked the lines of code with numbers to make you understand better.
So when we execute this piece of code even before the JavaScript engine executes Line 1, The JavaScript engine creates a global execution context(GEC), and during Phase 1 JavaScript Parser skims through the code and allocates memory to the variables and functions. Also, this GEC is pushed into the Call stack.
Here we can see the above pictorial representation after phase 1 is completed where variables are allocated memory and since the JS engine hasn't started to execute the code the value of variables is undefined at the moment and the function is assigned the whole function as it is.
Now Phase 2 which is the code execution phase JS engine runs through the program line by line and as soon as it executes Line 1, variable a
is assigned the value of 20 and similarly variable b
is assigned the value of 10. After this, the control directly goes to Line 7, but here JS engine encounters a function invoke so it forms a Function execution context(FEC) and pushes it into the call/Execution Stack on top of GEC.
When FEC is created and since we are passing the values of variables a
and b
to the function where e
and f
are parameters so their value would be equal to a
and b
respectively. When this FEC is formed it goes through the same step as phase 1 which is memory allocation and it also assigns the values for e
and f
as they have values from a
and b
which has global scope. The variable g
is assigned a value undefined.
At this time the control is at Line 3. Now the Code execution phase begins and when Line 4 is executed variable g
is assigned a value of 20. Finally, Line 5 is executed and the result is calculated. Let's see what the Execution context and Execution stack looks like at this point in time.
Here the FEC has a return value and as soon as Line 5 execution is completed the function execution is completed and it returns a value that is calculated inside the FEC and later that is stored in the variable c
. Since it is a function Expression. We will learn about function expression in some later blogs. Once the JS engine completely executes the whole function the FEC from the call stack is popped out.
Now control goes to Line 8 where we are printing the value of the variable c
and now the value will be printed which is 4000 from GEC and once all the code is finished executing the GEC is also popped out from the Execution stack and thus the process completes.
Conclusion:
Everything that happens in JavaScript happens inside Execution Context.
Execution Context is created in two phases
i. Memory Allocation/Creation Phase.
ii. Code Execution Phase.
There are mainly two important types of Execution context
i. Global Execution Context (GEC).
ii. Function Execution Context(FEC).
There is only 1 GEC in JS and there can be multiple FEC.
The execution of code is controlled by Execution Stack or Call Stack.
JS has only one Execution Stack.
Wow! It's good to still have you here. I hope you were able to pick some things about Execution Context. It is a very important concept as it will help you understand other important concepts easily like Hoisting, Lexical Environment, Closures, etc... More about these topics in another blog.
I tried my best to give you some clarity about the Execution context if you learn anything new please like the blog as it will motivate me to write even more articles frequently.
Subscribe to my newsletter
Read articles from Akash Raj directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Akash Raj
Akash Raj
I am a developer from India working professionally from past 2.5 years and I'm here to share my knowledge in JavaScript because I believe it's a beautiful language and most people interpret it wrong. I also write about React Native