Every time JavaScript runs code, it creates something called an Execution Context. Think of it as a box that holds everything the code needs to run — the variables, functions, and the value of this.
Two types of Execution Context
- Global Execution Context (GEC) — Created when the script first runs. There’s only one. It creates the
windowobject (in browsers) and setsthistowindow. - Function Execution Context (FEC) — Created every time a function is called. Each function gets its own execution context.
Two phases of every Execution Context
Every execution context goes through two phases:
1. Creation Phase (Memory Allocation)
Before running a single line of code, JavaScript scans the code and:
- Allocates memory for variables and sets them to
undefined - Stores the entire function declarations in memory
- Determines the value of
this - Sets up the Scope Chain (reference to the outer environment)
This is why hoisting works — variables and functions are already in memory before the code runs.
2. Execution Phase
Now JavaScript goes through the code line by line:
- Assigns actual values to variables
- Executes function calls (which create new execution contexts)
- Runs all the logic
var name = "Manish";
function greet() {
var message = "Hello";
console.log(message + " " + name);
}
greet();
// Creation Phase:
// name → undefined, greet → full function, this → window
// Execution Phase:
// name → "Manish", greet() called → new execution context created
The Call Stack
JavaScript uses a Call Stack to manage execution contexts. When a function is called, its execution context is pushed onto the stack. When it returns, it’s popped off.
function outer() {
var a = 10;
function inner() {
var b = 20;
console.log(a + b); // 30 — inner can access outer's variables via scope chain
}
inner(); // new execution context pushed onto stack
}
outer(); // new execution context pushed onto stack
Variable Environment and Scope Chain
Each execution context has a Variable Environment — the place where its local variables live. It also has a reference to its outer environment (the parent scope). This chain of references is the Scope Chain.
When JavaScript needs to find a variable, it first looks in the current Variable Environment. If it’s not there, it follows the Scope Chain upward until it either finds the variable or reaches the Global scope.
var global = "I'm global";
function first() {
var a = "I'm in first";
function second() {
var b = "I'm in second";
console.log(b); // found in current scope
console.log(a); // found via scope chain (first's scope)
console.log(global); // found via scope chain (global scope)
}
second();
}
first();
In simple language, every time JavaScript runs your code or calls a function, it creates a little environment with two phases — first it sets up memory (creation), then it runs the code (execution). These environments stack on top of each other in the Call Stack, and each one can look up to its parent for variables it doesn’t have locally.