Interview-Ready Reference | FAANG-Level Depth
- Execution Context
- Lexical Environment
- The Big Picture: How They Work Together
- Closures Explained
- Interview Traps & Edge Cases
- Quick Reference Tables
- One-Liners to Memorize
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.
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.
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
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
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)
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.
JavaScript manages contexts using a Call Stack (LIFO - Last In First Out).
function first() {
second();
}
function second() {
console.log("Hello");
}
first();Stack Flow:
| second() |
| first() |
| Global |
second()finishes → poppedfirst()finishes → popped- Global remains
Call Stack:
┌────────────────┐
│ FEC: second() │
├────────────────┤
│ FEC: first() │
├────────────────┤
│ GEC │
└────────────────┘
Each function call:
- Push context
- Execute
- Pop context
| 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 |
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.
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)
👉 JavaScript uses Lexical (Static) Scoping
This means:
- Scope is determined at write time
- Not at call time
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
Each {} creates a block lexical environment.
if (true) {
let x = 10;
const y = 20;
}
console.log(x); // ❌ ReferenceErrorBlock Lexical Env:
├── x
├── y
└── outer → global
❌ var ignores block scope.
When JS looks up a variable:
- Current lexical environment
- Parent lexical environment
- Continue until global
- If not found →
ReferenceError
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
| 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
┌─────────────────────────────────────┐
│ Execution Context │
│ ┌───────────────────────────────┐ │
│ │ Lexical Environment │ │
│ │ ├── Environment Record │ │
│ │ └── Outer Reference │ │
│ └───────────────────────────────┘ │
│ ├── this binding │
│ └── Variable Environment │
└─────────────────────────────────────┘
Definition: Closure = function + its lexical environment
function counter() {
let count = 0;
return () => {
count++;
return count;
};
}
const inc = counter();
inc(); // 1
inc(); // 2Why does count survive?
Because:
- Execution context of
counter()is destroyed - Lexical environment is retained
incholds reference to it
function foo() {
console.log(x);
}
function bar() {
let x = 10;
foo();
}
let x = 5;
bar(); // 5 ❌ Not 10✔️ Lexical scope, not call-site scope
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// 👉 Single lexical environment → 3 3 3for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// 👉 New lexical environment per iteration → 0 1 2✔️ Yes ❌ But not initialized → Temporal Dead Zone
console.log(a); // ❌ ReferenceError: Cannot access 'a' before initialization
let a = 10;✔️ Execution context exists
❌ No arguments object
❌ No own this
| Type | Hoisted? | Initialized? | TDZ? |
|---|---|---|---|
var |
✔️ Yes | ✔️ undefined |
❌ No |
let |
✔️ Yes | ❌ No | ✔️ Yes |
const |
✔️ Yes | ❌ No | ✔️ Yes |
function |
✔️ Yes | ✔️ Full definition | ❌ No |
| Scope Type | Created By | Variables |
|---|---|---|
| Global | Program start | var, let, const, function |
| Function | Function call | Local variables, parameters |
| Block | {} |
let, const only |
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 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.
Every execution context has a reference to a lexical environment. Execution contexts manage runtime flow; lexical environments manage scope and variable access.
-
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 🚀