What is Lexical Scope?
In JavaScript, lexical scope (also known as static scope) refers to the fact that the scope of a variable is determined by its position in the source code. When a function is defined, it captures variables from its surrounding (parent) scope at that specific place in the code — this forms a lexical environment.
Why is Lexical Scope Important?
Understanding lexical scope is crucial for mastering how variables are accessed, especially in nested functions and closures. It helps avoid bugs and makes your code more predictable.
Example 1: Basic Lexical Scope
let outerVar = "I am outside!";
function outerFunction() {
console.log(outerVar); // Can access outerVar due to lexical scope
}
outerFunction();
Output:
I am outside!
Here, the function outerFunction()
can access outerVar
because it's defined in the outer (lexical) environment.
Question:
What if we define another variable inside the function? Can it be accessed outside the function?
Answer:
No. Inner variables are not accessible from the outer scope. Lexical scope only works from outer to inner — not vice versa.
Example 2: Nested Functions and Lexical Scope
function outer() {
let outerMsg = "Hello from outer!";
function inner() {
console.log(outerMsg); // Can access because of lexical scope
}
inner();
}
outer();
Output:
Hello from outer!
Here, inner()
can access outerMsg
because it's defined inside outer()
, forming a lexical scope chain.
Example 3: What Happens When You Try to Access Inner Variables from Outside?
function wrapper() {
let secret = "Top Secret";
function reveal() {
return secret;
}
return reveal;
}
let func = wrapper();
console.log(func()); // Trying to access 'secret' indirectly
Output:
Top Secret
This example demonstrates closure — a function retaining access to its lexical scope even after the outer function has returned. Although secret
is not in the global scope, reveal
still has access to it.
Beginner Tip:
Think of lexical scope like a series of boxes. If you're in an inner box, you can see and use anything in the boxes around you. But if you're outside, you can't peek inside the smaller boxes.
Example 4: Scope Isolation
let a = "global";
function testScope() {
let a = "local";
console.log(a); // Refers to local 'a', not global
}
testScope();
console.log(a); // Refers to global 'a'
Output:
local global
This example proves that variables inside a function do not interfere with variables outside — thanks to lexical scoping.
Final Thoughts
- Lexical scope is determined at the time of writing code, not during execution.
- Functions remember the scope where they were defined, not where they were called from.
- This concept is the foundation of closures in JavaScript.
Practice Question
let message = "Hello";
function greet() {
console.log(message);
}
function run() {
let message = "Hi";
greet(); // What will this print?
}
run();
Answer:
Output:
Hello
Because greet()
was defined in the global scope, it retains access to the global message
, not the one in run()
.