← All concepts
Behind the Scenes

The Scope Chain

A variable lookup walks outward through nested scopes until it finds a match or runs out of places to look.

Loading visual…

Definition

Every function and block creates its own scope, and scopes can nest inside one another: a global scope, an outer function's scope, and an inner function's scope, for example. When code inside the innermost scope reads a variable, the engine first checks that scope's own bindings. If the name is not there, it steps out to the next enclosing scope and checks again, continuing outward link by link. This chain of enclosing scopes is fixed at the time a function is defined, not at the time it is called, which is why JavaScript uses lexical (static) scoping. The lookup stops as soon as a match is found, so a variable in an inner scope shadows one of the same name further out. If the chain is walked all the way to the global scope and still no binding exists, the engine throws a `ReferenceError`, because there is nowhere else to look.

Examples

const x = "global";
function outer() {
  const y = "outer";
  function inner() {
    console.log(x, y); // global outer
  }
  inner();
}
outer();

inner() has no x or y of its own, so it walks the scope chain outward: first to outer's scope for y, then to the global scope for x.

function outer(x) {
  function inner() { return x + 10; }
  return inner();
}
outer(5); // 15

inner reads x from the enclosing outer scope through the scope chain, even though x is not a parameter of inner itself.

Where you see this

Practice this

Further reading