1️⃣ Lexical Environment
Whenever a JavaScript Execution Context is created (like when you run global code or call a function), a Lexical Environment is also created to store all the variables, functions, and references that are accessible in that context.
So, LE = local memory + reference to parent LE.
A Lexical Environment is the structure that JavaScript’s engine uses to store variable bindings (and function declarations) along with a reference to its outer environment.
A lexical environment is the place where variables and functions are stored and looked up based on where your code is written, not where it’s called.
Think of a Lexical Environment as a hidden “backstage notebook” where variables live for a given chunk of code.
JavaScript uses lexical scoping, meaning the scope chain is determined by where functions are written, not where they are called.
In simpler words:
- It’s a special object that holds all variables/functions in the current scope.
- It also contains a link to the outer scope’s lexical environment.
- This link is what creates the scope chain.
“Lexical” means based on where the code is written — not where it is called from.
This means the outer environment reference is set when the function is defined, not when it’s executed.
It has two parts:
- Environment Record – Stores all variable/function declarations for that scope. The actual place where variables, functions, and parameters are stored.
- Outer Lexical Environment Reference – Points to the outer scope. A pointer to the “notebook” of the surrounding code, so JS can look up variables it doesn’t find locally.
Lexical Environment Creation
Whenever a function is invoked:
- A new Lexical Environment is created.
- All variables declared inside are stored in the Environment Record.
- The outer environment reference is set based on where the function was defined.
📌 Key points:
- Created when a scope is entered (e.g., function call, block scope
{}). - Based on where code is written, not where it’s called — this is why it’s called lexical (from “lexicon” = words/code location).
- Used heavily in closures.
Example:
function outer() {
let a = 10;
function inner() {
console.log(a); // Found in outer's lexical environment
}
inner();
}
outer();
Here:
inner’s Lexical Environment → has its own local variables and a reference toouter’s environment.- That “reference” is what lets
inner()seeaeven afterouter()has finished.
2️⃣ Surrounding State
The surrounding state is basically the combination of:
- Variables
- Functions
- Parameters
…that are available in the outer scopes when a function is created.
The surrounding state is the set of variables, functions, and their values from the outer (parent) lexical environment that an inner function can access.
It’s the actual data & references from the outer lexical environments that a function can close over.
Think of it this way:
- Lexical Environment = blueprint + pointer to outer scopes.
- Surrounding State = actual values in those outer scopes at that point in time.
Example showing both:
function makeCounter() {
let count = 0; // part of surrounding state for `increment`
function increment() {
count++;
console.log(count);
}
return increment;
}
const counter = makeCounter();
counter(); // 1
counter(); // 2
Here:
increment’s Lexical Environment contains a reference tomakeCounter’s environment.countlives in that surrounding state, andincrementcan keep updating it because of the closure.
✅ In short:
- Lexical Environment = how JS organizes and links variable storage at runtime based on where code is written.
- Surrounding State = the actual variables and values from outer scopes that a function has access to because of its lexical environment.
