In this article, I'll try to explain to you what is execution context and how it is created with easy examples. It is a complete beginner tutorial.
Let's guess an output first
console.log(a)
b()
bb()
var a = 10;
function b() {
var c = 20;
console.log(c)
}
var bb = () => {
var cc = 30;
console.log(cc)
}
Output will be
If you guessed it right then you have a good understanding of how javascript code is run under the hood.
For those who were unable to guess it right, let's first understand what is execution context.
Let me start with the core fundamental, i.e
Everything in javascript happens inside an execution context.
It is like a big box, in which it has two components
- Variable Environment (memory component)
- Thread of Execution (code component)
In the variable component, memory is allocated to all the variables and function present in the code and stored as key-value pair.
In the code component, the actual code is run line by line from top to bottom, as it is written by the user.
Now let's take a simple code example and see how this execution context is created.
var a = 10;
function b () {
var c = 20;
console.log(c);
}
console.log(a);
b();
First, a Global execution context(GEC) is created and is put inside the call stack.
Global execution context is created in two-phase
1. First is memory allocation(compile phase)
Line1 - Engine sees a variable a, allocates memory to it, and gives an initial value undefined to it.
Line3 - Then it sees a function b, allocates memory to it but for functions, it is a little different, it literally copies the whole function and stores it in the value.
No other variable and function present, so phase 1 is complete. Ya Ok, you might me thinking there is another variable c inside the function b, what happened to that?. The variable c is inside a function scope so it will not be stored inside the global scope. We will see this later below.
Let me put a debugger on line 1 to show how it looks like in a browser.
This memory allocation is called Hoisting
Hoisting: the variable and function declarations are put into memory during the compile phase.
2. Second is code execution phase
Now javascript once again runs through the code line by line. This is the phase where all functions and calculations are executed.
Line1 - Now the engine replaces the value undefined and assigned a value 10 to the identifier a.
now it directly moves to line 8 as no variable or no function is invoked between line 2 to 7
Line8 - Executes the line and prints 10 in the console.
Line9 - Function b is invoked. Whenever a function is invoked a new local execution context is created inside the execution context where it was invoked and it is put inside the call stack.
Line3 - Then again, this local execution context is created in two-phase.
- Memory allocation: Variable c is allocated a memory with value undefined
Line4 - Code inside the function b is executed
- Code execution: C is assigned a value 20
Line5 - Executes the line and prints 20 in the console
once the entire function execution is complete, the local execution context vanishes and it is also popped out of the call stack. And the control is back to line 9
And after the entire code is completely executed, the global execution context is also popped out of the call stack
Now let's go back to the first example we took.
console.log(a)
b()
bb()
var a = 10;
function b() {
var c = 20;
console.log(c)
}
var bb = () => {
var cc = 30;
console.log(cc)
}
let me go through the execution of the above javascript code
Phase1: Memory allocation
First memory is allocated to all the variables and functions in the memory component of the global execution context.
here you can see function bb and function b has different values. One has undefined and the other has the entire function. Why this?
This is because b is a function statement & bb is a function expression. The one difference is that, how these both functions are hoisted.
Function b is hoisted as a normal function
Function bb is hoisted as another variable. So it is assigned a value undefined.
Phase2: Code execution
Now when the engine starts to execute the code from top to bottom.
Line1: - Prints the value of variable a as undefined. Because we now know that the variable a will be assigned a value of 10 at Line5
Line2: - Function b is invoked. A new local execution context is created and put inside the call stack. Control moves to Line 7 and again the entire process occurs to create the local execution context. And then its Prints the value of variable c as 20. Control then again moves to Line2
Line3: - As bb is stored as a variable. We cannot invoke it as a function. So the error is thrown on the console as Uncaught TypeError: bb is not a function
Now no variables or functions are invoked further in the code. So the execution is complete and the global execution context is also popped out of the call stack
So the output will be
Conclusion
In this article, we learned what is execution context, how it is created, and also what is hoisting. So now you can use the concept of execution context to analyze any code and how it will be executed under the hood and can predict the write output.
Thank you for reading the blog😍. If you liked it, please share it with your developer friends who might find it useful too.