1. JavaScript Execution Overview
JavaScript runs in two main phases for any given code:
- Creation Phase (a.k.a. “Memory Allocation Phase”)
- Variables and functions are set up in memory before any code actually runs.
- Functions are fully stored in memory.
- Variables are assigned
undefined(forvar) or left in TDZ (Temporal Dead Zone) forlet/constuntil initialized.
Happens before any code is executed.
- Variables declared with
vargetundefined. - Functions are hoisted fully (function declarations, not expressions).
letandconstare placed in Temporal Dead Zone (TDZ) — you can’t access them before their line of code executes.thisis set (depends on how the code runs).- Outer scope reference (Lexical Environment link) is set.
2. Execution Phase
- Code is executed line-by-line.
- Variables get actual values.
- Functions get called and create new execution contexts.
Lexical Environment & Scope Chain
Lexical Environment =
Current EC’s Variable Environment + Reference to Outer Environment.
- When a variable is not found in the current EC, JavaScript follows the scope chain outward.
- This is based on where functions are physically written in the code (lexical scope), not where they’re called from.
Example:
let x = 10;
function outer() {
let y = 20;
function inner() {
console.log(x, y); // looks in inner → outer → global
}
inner();
}
outer(); // prints 10 20
📌 Even though inner() is executed inside outer(), it remembers where it was written, so it can access x and y.
2. Execution Context
An Execution Context (EC) is an environment where JavaScript code is evaluated and executed.
There are three types:
- Global Execution Context (GEC) – Created first, runs your whole file.
thisrefers to the global object (windowin browsers,globalin Node.js).
- Function Execution Context (FEC) – Created when a function is invoked.
- Eval Execution Context – Rare, for
eval()calls.
Every EC has three main parts:
- Variable Environment – Stores variables and function declarations.
- Lexical Environment – Keeps track of variable scope and outer scope reference.
thisBinding – Sets the value ofthisdepending on how the function is called.
3. Call Stack
The Call Stack is where JavaScript keeps track of which execution context is currently running.
- It’s LIFO (Last In, First Out).
- When a function is called, a new EC is pushed onto the stack.
- When a function finishes, its EC is popped from the stack.
JavaScript runs synchronously in the call stack, but asynchronous tasks (timers, API calls, promises) use:
- Web APIs → handle async work in browser/Node.
- Callback Queue / Task Queue → stores callbacks ready to run.
- Event Loop → moves tasks from the queue into the call stack when it’s empty.
Example:
console.log("1");
setTimeout(() => {
console.log("2");
}, 0);
console.log("3");
// Output: 1 → 3 → 2
Here:
"1"goes straight to stack → printed.setTimeoutsends the callback to Web API, waits for timer → then moves it to queue."3"is printed.- Event loop sees stack empty → pushes
"2"callback to stack.
4. Step-by-Step Example
var a = 10;
function foo() {
var b = 20;
console.log('Inside foo');
bar();
}
function bar() {
console.log('Inside bar');
}
foo();
console.log('Done');
Step 1: Creation Phase (Global Execution Context)
- Memory is set up:
a: undefined foo: function bar: function thispoints towindow(browser).- Outer environment is
null(no parent above global).
Step 2: Execution Phase (Global EC)
a = 10foo()is called → new Function Execution Context forfoois created and pushed onto Call Stack.
Step 3: Function foo Execution
- Creation phase for
foo:b: undefined - Execution phase:
b = 20console.log('Inside foo')→ prints"Inside foo"bar()is called → new Function Execution Context forbaris created and pushed.
Step 4: Function bar Execution
- Creation phase for
bar: (no vars except defaultarguments) - Execution phase:
console.log('Inside bar')→ prints"Inside bar"
barfinishes → popped from stack.
Step 5: Back to foo
foofinishes → popped from stack.
Step 6: Back to Global
- Executes
console.log('Done')→ prints"Done". - Global EC stays until program ends.
5. Call Stack Flow (Visual)
Initially:
[ Global EC ]
After foo() call:
[ foo EC ]
[ Global EC ]
Inside foo, after bar() call:
[ bar EC ]
[ foo EC ]
[ Global EC ]
After bar returns:
[ foo EC ]
[ Global EC ]
After foo returns:
[ Global EC ]
6. Key Notes
- JavaScript is single-threaded → only one thing happens at a time in the call stack.
- If a function takes too long, it blocks the call stack.
- Async operations (
setTimeout, Promises, fetch) work with Web APIs + Callback Queue + Event Loop, not directly in the stack.
