Lexical Scope

⭐ Interview Importance: HIGH
⏱️ Revision Time: 4 min

TL;DR

Lexical Scope (also known as Static Scope) means that the accessibility of variables is determined by the physical placement of functions inside your source code. A function always has access to the variables defined in its outer (parent) scopes, exactly as they are written in the file, regardless of where or how the function is later called.

Mental Model

How It Works

When the JavaScript engine compiles your code, it creates a “Scope Chain”.
If a variable is used inside a function, the engine looks for it in this order:

  1. Inside the function’s own local scope.
  2. If not found, it moves UP to the parent function’s scope (based on where the code was physically typed).
  3. It repeats this until it hits the Global Scope.
  4. If it’s not in the Global Scope, it throws a ReferenceError.

The engine never looks down into child scopes. Parent functions cannot see inside their children.

Example

const user = "Alice"; // Global Scope

function outer() {
  const account = "Premium"; // Outer Scope

  function inner() {
    const balance = 100; // Inner Scope
    
    // Lexical Scope in action: inner() can see all outer variables!
    console.log(`${user} has a ${account} account with $${balance}.`);
  }

  inner();
  
  // console.log(balance); // ERROR! Outer cannot see Inner's variables.
}

outer();

Common Output Question

const value = "Global";

function printValue() {
  console.log(value);
}

function execute() {
  const value = "Local";
  printValue();
}

execute();

Q: What does this output and why?
A: Global.
This demonstrates Lexical Scope perfectly. Even though printValue() is called from inside execute() (where value = "Local"), JavaScript uses Lexical Scope, not Dynamic Scope. The engine looks at where printValue was physically written in the code. It was written in the global scope, so its parent scope is the global scope. Therefore, it finds the global value.

Senior Interview Question

Q: Explain the difference between Lexical Scope and Execution Context.

A: Lexical Scope is established at compile-time. It is static and determined purely by where you type your curly braces {} in the source file. It defines the rules for variable lookup (the Scope Chain).

Execution Context, on the other hand, is a runtime concept. It is created dynamically every time a function is called. While the Execution Context contains a reference to the Lexical Scope (the Outer Environment Reference), it also contains runtime-specific data like the value of this and the arguments object, which can change drastically depending on how the function was invoked (e.g., using .call() or as an object method).