Chapter IX · Scope

Lexical Scope

Lexical scope means a function's access to outer variables is fixed by where the function is physically written in the source code — not by where or how it's later called.

01 How It Works

Think of a set of Russian nesting dolls: each inner doll can "see" the shells around it because it was assembled inside them — moving the whole set to a different shelf later doesn't change which dolls surround which.

"Lexical" refers to the lexing/parsing stage of reading source code — before anything even runs, the engine can already tell, purely from nesting and indentation, exactly which outer variables any given inner function will be allowed to reach. This is what makes JavaScript's scoping predictable: you can determine a variable's scope just by reading the code, without having to trace every possible call path at runtime. It's also the mechanism that closures are built on — a function permanently keeps access to the scope it was lexically written inside, wherever it's later called from.

example.js
function outer() {
  let outerVar = "outer";
  function inner() {
    console.log(outerVar); // lexically accessible — inner() is written inside outer()
  }
  inner();
}
outer(); // "outer"
  1. 1. Functions are nested according to how the source code is physically written.

  2. 2. Each nested function's outer scope is fixed at the point it's defined, based on that nesting.

  3. 3. No matter where or when the function is later called, it always looks outward through the same lexical chain.

02 Practical Example

Here is how you might see this concept applied in real-world code:

practical.js
const message = "Hello";

function showMessage() {
  console.log(message); // fixed by where showMessage is written, not by who calls it
}

function runElsewhere(fn) {
  const message = "Different message"; // this local "message" is irrelevant
  fn();
}

runElsewhere(showMessage); // still logs "Hello" — lexical scope, not call-time scope

Key Takeaway

A function's outer scope is locked in by where it's written in the code, never by where it's called from — this is what makes JavaScript's variable resolution predictable, and it's the foundation closures rely on.

Related Concepts