Skip to main content

Lexical scope

Lexical scope is the scope defined by where the code sits at the moment it is written, not at the moment it runs. Which function has access to which variables is decided at declaration time, when the engine reads the source, not when you call the function.

Theory

TL;DR

  • Lexical scope is determined by where the code is placed in the program text.
  • Access to variables is decided at declaration and parse time, not at call time.
  • An inner function sees the variables of every function it is nested in, plus the globals.
  • Name lookup walks up the scope chain: inner -> outer -> global.
  • Languages with dynamic scope (Bash, old Lisp) do the opposite: the caller decides.
  • Closures are the practical consequence of lexical scope.

Quick example

javascript
let a = 10; function outer() { let b = 20; function inner() { let c = 30; console.log(a, b, c); // 10 20 30 } inner(); } outer();

Here inner is declared inside outer, so it has access to the variables of outer and to the globals. JavaScript memorised that structure at declaration, not at the call.

The scope chain:

javascript
inner -> outer -> global

Why it is called "lexical"

The word "lexical" means "relating to the text of the program". The engine "remembers" where functions and blocks sit while parsing, when it reads the source file, and not when you call the functions.

The practical consequence: you can work out any function's scope just by looking at the text of the file, without running the program. That is exactly why linters and IDEs can highlight unreachable or shadowed variables before anything executes.

Lexical versus dynamic scope

Some languages (Bash or old Lisp, for example) use dynamic scope: it is determined by whoever called the function. In JavaScript the scope is lexical: it is determined by where the function is written.

javascript
let x = "global"; function foo() { console.log(x); } function bar() { let x = "local"; foo(); // who called foo? bar, but... } bar();

Result:

javascript
global

Because foo is declared in the global scope, JavaScript looks for x there, not at the place it was called from (bar).

This is the essence of lexical scope: "look where the function is written, not where it is called from".

Closures, lexical scope in practice

javascript
function makeCounter() { let count = 0; return function() { count++; console.log(count); }; } const counter = makeCounter(); counter(); // 1 counter(); // 2

Here the inner function memorised the lexical environment of makeCounter and still "sees" count even after the outer function has finished.

This works only because the scope is lexical and not dynamic: the reference to the outer environment is baked into the function when it is created, so it lives as long as the function itself.

Visually

javascript
[ Global Scope ] a = 10 | [ outer() Scope ] b = 20 | [ inner() Scope ] c = 30

The function inner always "knows" where to look for a and b, because that was fixed at declaration time.

Summary

ConceptDescription
Lexical scopeThe scope in which a function "sees" variables; determined by its position in the source code
Determined whenWhile the code is written and parsed, not while it runs
Why it existsSo the engine knows which variables are available to each function
Related toLexical Environment, Scope Chain, Closures

Common mistakes

  • Assuming scope depends on the call site. It does not, only on the declaration site in the program text.
  • Expecting foo() in the example above to see the local x from bar. That is dynamic scope behaviour, which JavaScript does not have.
  • Confusing lexical scope with this. In ordinary functions this is in fact resolved dynamically, at call time; only arrow functions take it lexically.
  • Thinking that an outer function's variables are guaranteed to disappear once it returns. If a closure holds a reference to them, they stay alive.
  • Confusing lexical scope with hoisting. Hoisting answers "when does a variable become usable", lexical scope answers "where do we look for it at all".

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.