JavaScript Execution Context & Lexical Environment - Complete Guide
Interview-Ready Reference | FAANG-Level Depth
Table of Contentsโ
- Execution Context
- Lexical Environment
- The Big Picture: How They Work Together
- Closures Explained
- Interview Traps & Edge Cases
- Quick Reference Tables
- One-Liners to Memorize
1. Execution Contextโ
Core Conceptโ
Execution Context = the environment in which JavaScript code is evaluated and executed
Think of it as a runtime box that stores:
- Variables
- Functions
- Scope chain
thisvalue
Key Rule: JavaScript always runs inside an execution context. No context โ no execution.
Types of Execution Contextsโ
JavaScript has 3 main types:
- Global Execution Context (GEC)
- Function Execution Context (FEC)
- Eval Execution Context (rare, ignore in interviews)
We'll focus on GEC + FEC.
Global Execution Context (GEC)โ
When is it created?
- Immediately when JS file starts executing
- Only one GEC per program
What does GEC contain?
-
Global Object
- Browser โ
window - Node.js โ
global - Global variables & functions attach here
- Browser โ
-
this- In browser โ
this === window - In strict mode โ
undefined
- In browser โ
-
Memory & Code Phases
๐ GEC is created in two phasesโ
Phase 1: Memory Creation (Hoisting Phase)
var a = 10;
let b = 20;
function foo() {
console.log("hello");
}
Memory Phase:
aโundefinedbโ<uninitialized>(Temporal Dead Zone)fooโfunction reference
Phase 2: Code Execution Phase
- Values assigned
- Code executed line by line
aโ10bโ20
Function Execution Context (FEC)โ
When is it created?
- Every time a function is invoked
- Each call gets a new execution context
What does a Function Execution Context contain?
- Arguments object
- Local variables
- Inner function declarations
thisvalue- Scope chain (lexical environment)
Exampleโ
function add(x, y) {
let sum = x + y;
return sum;
}
add(2, 3);
FEC Creation Phases
Phase 1: Memory Creation
xโ2yโ3sumโ<uninitialized>
Phase 2: Execution
sum = 5return 5
Once return executes โ FEC is destroyed.
Call Stack (Execution Context Stack)โ
JavaScript manages contexts using a Call Stack (LIFO - Last In First Out).
Exampleโ
function first() {
second();
}
function second() {
console.log("Hello");
}
first();
Stack Flow:
| second() |
| first() |
| Global |
second()finishes โ poppedfirst()finishes โ popped- Global remains
Visual Mental Model (Interview Gold)โ
Call Stack:
โโโโโโโโโโโโโโโโโโ
โ FEC: second() โ
โโโโโโโโโโโโโโโโโโค
โ FEC: first() โ
โโโโโโโโโโโโโโโโโโค
โ GEC โ
โโโโโโโโโโโโโโโโโโ
Each function call:
- Push context
- Execute
- Pop context
Global vs Function Execution Context (Comparison)โ
| Feature | Global EC | Function EC |
|---|---|---|
| Created | On program start | On function call |
| Count | Only one | Multiple |
| Variables | Global variables | Local variables |
this | window (browser) | Depends on call |
| Lifetime | Till program ends | Till function returns |
2. Lexical Environmentโ
Core Conceptโ
Lexical Environment = where variables are physically written in the code
Not when code runs โ but where it is defined.
It decides:
- Scope
- Variable lookup
- Closure behavior
"Lexical" = based on code structure, not runtime flow.
Formal Definition (Interview-safe)โ
A Lexical Environment is a data structure that contains:
- Environment Record โ stores variables & functions
- Outer Reference โ link to the parent lexical environment
Lexical Environment
โโโ Environment Record
โโโ Outer (reference to parent)
Lexical Scope (Core Rule)โ
๐ JavaScript uses Lexical (Static) Scoping
This means:
- Scope is determined at write time
- Not at call time
Exampleโ
const a = 10;
function outer() {
const b = 20;
function inner() {
console.log(a, b);
}
inner();
}
outer();
Scope Chain:
innerโouterโglobalafound in globalbfound in outer
โ๏ธ This chain is decided before execution starts
Block Scope (let / const)โ
Each {} creates a block lexical environment.
if (true) {
let x = 10;
const y = 20;
}
console.log(x); // โ ReferenceError
Block Lexical Env:
โโโ x
โโโ y
โโโ outer โ global
โ var ignores block scope.
Scope Chain (Variable Resolution)โ
When JS looks up a variable:
- Current lexical environment
- Parent lexical environment
- Continue until global
- If not found โ
ReferenceError
Exampleโ
let a = 1;
function foo() {
let b = 2;
function bar() {
let c = 3;
console.log(a, b, c);
}
bar();
}
Lookup order in bar():
cโ barbโ fooaโ global
3. The Big Picture: How They Work Togetherโ
Execution Context vs Lexical Environmentโ
| Execution Context | Lexical Environment |
|---|---|
| Created at runtime | Defined by code structure |
| Manages execution | Manages scope |
| Pushed to call stack | Linked via outer references |
| Destroyed after execution | May survive (closures) |
๐ Execution context contains a reference to its lexical environment
Complete Mental Modelโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Execution Context โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Lexical Environment โ โ
โ โ โโโ Environment Record โ โ
โ โ โโโ Outer Reference โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โโโ this binding โ
โ โโโ Variable Environment โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
4. Closures Explainedโ
Definition: Closure = function + its lexical environment
function counter() {
let count = 0;
return () => {
count++;
return count;
};
}
const inc = counter();
inc(); // 1
inc(); // 2
Why does count survive?
Because:
- Execution context of
counter()is destroyed - Lexical environment is retained
incholds reference to it
5. Interview Traps & Edge Casesโ
โ ๏ธ Trap 1: Lexical โ Dynamicโ
function foo() {
console.log(x);
}
function bar() {
let x = 10;
foo();
}
let x = 5;
bar(); // 5 โ Not 10
โ๏ธ Lexical scope, not call-site scope
โ ๏ธ Trap 2: var vs let in loopsโ
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// ๐ Single lexical environment โ 3 3 3
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// ๐ New lexical environment per iteration โ 0 1 2
โ ๏ธ Trap 3: Are let and const hoisted?โ
โ๏ธ Yes โ But not initialized โ Temporal Dead Zone
console.log(a); // โ ReferenceError: Cannot access 'a' before initialization
let a = 10;
โ ๏ธ Trap 4: Does arrow function have its own execution context?โ
โ๏ธ Execution context exists
โ No arguments object
โ No own this
6. Quick Reference Tablesโ
Hoisting Behaviorโ
| Type | Hoisted? | Initialized? | TDZ? |
|---|---|---|---|
var | โ๏ธ Yes | โ๏ธ undefined | โ No |
let | โ๏ธ Yes | โ No | โ๏ธ Yes |
const | โ๏ธ Yes | โ No | โ๏ธ Yes |
function | โ๏ธ Yes | โ๏ธ Full definition | โ No |
Scope Typesโ
| Scope Type | Created By | Variables |
|---|---|---|
| Global | Program start | var, let, const, function |
| Function | Function call | Local variables, parameters |
| Block | {} | let, const only |
7. One-Liners to Memorizeโ
Execution Contextโ
Execution Context is the runtime environment where JavaScript code runs. The global execution context is created first, and every function invocation creates its own execution context, all managed via the call stack.
Lexical Environmentโ
Lexical Environment defines where variables live based on code structure, and JavaScript resolves variables using a scope chain formed via outer lexical references. Closures work because functions retain access to their defining lexical environment.
The Connectionโ
Every execution context has a reference to a lexical environment. Execution contexts manage runtime flow; lexical environments manage scope and variable access.
Common Microsoft/Google Follow-up Questionsโ
-
Difference between Scope chain vs Call stack?
- Call stack = execution order (runtime)
- Scope chain = variable lookup (code structure)
-
How closures cause memory leaks?
- Retained lexical environments aren't garbage collected
- If large objects are in outer scope, they persist
-
Lexical environment vs Context object?
- Lexical env = scope structure
- Context object =
thisvalue
-
How
thisdiffers from lexical scope?thisis dynamic (call-site dependent)- Lexical scope is static (write-time dependent)
End of Guide | Bookmark this for interviews ๐