In Part 1, we explored how JavaScript runs under the hood and discussed the JavaScript engine and runtime environment.
In this part, we’re going deeper.
We will understand:
- What is Execution Context?
- What are the different phases and types of an Execution Context?
- What is the Call Stack?
- How functions are executed internally? And most importantly we’ll visualise everything with a simple code example.
Let’s begin.
What is an Execution Context in JavaScript?
Whenever JavaScript runs your code, it creates a special environment called an Execution Context.
Think of it as a container where JavaScript keeps everything needed to execute your code.
Phases of Execution Context
Each execution context goes through two phases:
1. Creation Phase (Memory Allocation Phase)
Before executing your code, JavaScript:
- Scans the code
- Allocates memory for variables
- Stores function definitions in memory
Important behavior:
- Variables declared with
varare initialized withundefined - Functions are stored entirely in memory
-
letandconstare hoisted but kept in a temporal dead zone No code is executed here. Only memory setup happens.
2. Execution Phase
In this phase, JavaScript:
- Executes code line by line
- Assigns actual values to variables
- Runs functions when invoked
- Evaluates expressions
This is where real execution happens.
Types of Execution Context
There are two main types of execution context:
1.Global Execution Context (GEC)
- Created when JavaScript starts running your file
- Exists only once and stays in the Call Stack until the program closes
- Represents the global scope
2.Function Execution Context (FEC)
- Created whenever a function is called or invoked
- Each function call creates a new execution context
- Has its own memory and thread of execution
What’s Inside an Execution Context?
Thread of Execution
This is the order in which JavaScript runs your code line by line.
JavaScript is (initially) single-threaded, meaning it executes one line at a time.
Memory
Each execution context has its own memory.
- Global context → Global memory
- Function context → Local memory
This is why variables inside functions are not accessible outside (unless returned).
What is the Call Stack?
JavaScript uses a special memory structure to keep track of all execution contexts called the Call Stack.
It follows LIFO structure, i.e., "Last In, First Out" (like a stack of plates).
- The last function added to the stack, will be executed first, and will be popped out of the stack first.
How all of this works: Step-by-Step!
Let’s understand this using a simple example.
const firstName = "Munzah";
const lastName = "Shah";
const age = 27;
const designation = "Software Engineer";
function createFullName() {
return firstName + " " + lastName;
}
function displayUserDetails() {
console.log("Full Name:", createFullName());
console.log("Age:", age);
console.log("Designation:", designation);
}
displayUserDetails();
Step-by-Step Execution Breakdown
Step 1: Global Execution Context is Created
When the file runs:
- Global Execution Context (GEC) is created
- It is pushed into the Call Stack
Call Stack:
| Global |
Step 2: Creation Phase of Global Context
Memory is allocated:
firstName → undefined
lastName → undefined
age → undefined
designation → undefined
createFullName → function definition
displayUserDetails → function definition
Step 3: Execution Phase Begins
Now values are assigned:
firstName → "Munzah"
lastName → "Shah"
age → 27
designation → "Software Engineer"
Functions are still not executed just stored.
Step 4: Function Invocation Happens
When this line runs:
displayUserDetails();
A new Function Execution Context is created.
Call Stack becomes:
| displayUserDetails |
| Global |
Now JavaScript executes displayUserDetails.
Step 5: Inside displayUserDetails()
The thread of execution encounters another function call:
createFullName()
Another Function Execution ExecutionContext is created.
Call Stack now looks like this:
| createFullName |
| displayUserDetails |
| Global |
Step 6: createFullName Executes
It returns:
"Munzah Shah"
Once function is completed:
- Its result is returned to the parent execution context.
- And It's execution context is popped out from the stack.
So now, call Stack becomes:
| displayUserDetails |
| Global |
Step 7: Remaining Code In displayUserDetails() Function Executes
Now:
Age: 27
Designation: Software Engineer
After finishing the execution of this function:
- displayUserDetails() context is removed
- Stack pointer goes back to Global
Call Stack:
| Global |
Important Rule to Remember
JavaScript always executes the function that is on the top of the Call Stack.
That’s why it follows LIFO.
Final Output of This Code
Full Name: Munzah Shah
Age: 27
Designation: Software Engineer
Why Understanding This is Important
If you understand:
- Execution Context
- Call Stack
- Creation Phase
- Execution Phase
You will easily understand:
- Hoisting
- Scope
- Closures
- Asynchronous JavaScript
- Event Loop
And that’s when JavaScript truly starts making sense.
Summary
- JavaScript creates a Global Execution Context (GEC) when a program starts running.
- Every execution context goes through two phases:
- Creation Phase (memory allocation)
- Execution Phase (code runs line by line)
- Variables and function definitions are stored in memory during the creation phase.
- Each function call creates a new Function Execution Context (FEC).
- Every execution context contains:
- Its own memory
- A thread of execution
- JavaScript uses a Call Stack to manage execution contexts.
- The Call Stack follows the **Last In, First Out (LIFO) **principle.
- The function at the top of the stack is executed first.
- Once a function finishes execution, it is removed (popped) from the stack.
- The Global Execution Context remains until the program finishes running.
- Understanding execution context and call stack makes advanced concepts like hoisting, closures, and async JavaScript easier to understand.
Stay connected with hasabTech for more information:
Website | Facebook | LinkedIn | YouTube | X (Twitter) | TikTok
Top comments (0)