Whenever JavaScript runs code, the engine needs a workspace to manage what’s happening. This workspace answers key questions:
- Which variables and functions are available? → Scope
- Where should I look if a variable isn’t here? → Scope Chain
- What is this right now? → Context Object
This workspace is called an Execution Context, and every execution context contains three main components:
*Lexical Environment (LE) *→ Stores variables, functions, parameters, and references to outer environments.
Variable Environment (VE) → Internal storage mainly for var declarations and function declarations.
this binding → Determines the current context object.
Types of Execution Contexts
Global Execution Context (GEC) → Created first when JS starts. Holds the Global Lexical Environment. Only one GEC exists.
Function Execution Context (FEC) → Each function call creates a new Execution Context with its own Lexical Environment (local variables, arguments, inner functions). Its Outer points to the parent scope (where the function was defined).
Eval Execution Context (EEC) → Created when using eval("..."). Runs code from a string. ⚠️ Rarely used and considered bad practice (security + performance issues).
Example 1 – Global + Function Execution Context
// Global Execution Context
var name = "Metin";
function sayHello() {
// Function Execution Context
var greeting = "Hello";
console.log(greeting + ", " + name);
}
sayHello();
Now lets go analyze Step-by-Step:
- Global Execution Context (GEC) created:
Lexical Environment: { name: "Metin", sayHello: <function> }, Outer: null
Scope: name, sayHello
Scope Chain: Only global
this: window (browser) or global (Node.js)
- Function Execution Context (FEC for sayHello) created:
Lexical Environment: { greeting: "Hello" }, Outer → Global Lexical Environment
Scope: greeting
Scope Chain: Function scope → Global scope
this: undefined (strict mode)
Variable lookup:
greeting → found in FEC
name → not in FEC → check outer → Global LE → found "Metin"
Output:
Hello, Metin
Example 2 – Lexical Environment and Closures
function outer() {
let counter = 0; // outer lexical environment
function inner() {
counter++; // inner still "remembers" outer's variables
console.log(counter);
}
return inner;
}
const fn = outer();
fn(); // 1
fn(); // 2
fn(); // 3
Step-by-Step
- Call outer() → FEC for outer created:
Lexical Environment: { counter: 0, inner: <function> }, Outer → Global LE
Scope: counter, inner
Scope Chain: outer → global
this: undefined (strict mode)
inner returned → closure formed → retains reference to outer LE
- Call fn() → FEC for inner created:
Lexical Environment: {}, Outer → Lexical Environment of outer()
Scope: empty
Scope Chain: inner → outer → global
this: undefined
Variable lookup:
counter → not in inner → outer LE → found → incremented
Output sequence:
1
2
3
Top comments (0)