JavaScript Scope Chain

The scope chain determines where JavaScript searches for an identifier when resolving a variable reference. It connects the current lexical environment to its outer environments and is fundamental to understanding closures.

JavaScript uses lexical scoping: an identifier is resolved according to where the code is written, not where a function is called. When JavaScript encounters a variable reference such as `name`, it first checks the current scope and then searches outward through enclosing scopes until it finds a matching binding or reaches the global scope.

Each function creates its own local scope, while blocks such as `if`, `for`, and `{}` can create block scopes for `let` and `const`. A nested function can access bindings from its enclosing scopes because those scopes are part of its lexical environment.

The scope chain is especially important for closures. A function retains access to variables from the lexical scopes surrounding its definition even after the outer function has finished executing. The inner function does not copy the variable's value; it retains access to the relevant binding.

If a name exists in multiple scopes, the nearest matching binding is used. This is called shadowing. The search stops when a matching binding is found, so an inner variable can hide an outer variable with the same name.

Key points

Interview questions

Is JavaScript scope determined by where a function is called?

No. JavaScript uses lexical scoping, so a function resolves free variables according to where the function was defined. The caller's local variables do not become part of the called function's scope chain. This distinction is important when reasoning about callbacks and closures.

How does the scope chain relate to closures?

A closure occurs when a function retains access to bindings from its surrounding lexical environment. When the function later runs, identifier lookup can travel through those retained environments. This allows an inner function to use variables from an outer function even after the outer function has returned. The retained environment is why closures can preserve state across calls.

What is the scope chain in JavaScript?

The scope chain is the sequence of lexical environments JavaScript searches when resolving an identifier. Lookup begins in the current scope and moves outward through enclosing scopes. If a matching binding is found, that binding is used and the search stops. This mechanism is based on lexical structure rather than the function's caller.

What happens when an inner scope declares a variable with the same name as an outer variable?

The inner declaration shadows the outer declaration. A reference to that name from inside the inner scope resolves to the nearest matching binding. Code outside the inner scope can still access the outer binding if it is otherwise visible. Shadowing does not modify or remove the outer variable.

How do `var`, `let`, and `const` differ in scope?

`let` and `const` are block-scoped, so their bindings are limited to the nearest enclosing block. `var` is function-scoped, so a `var` declaration belongs to the nearest function scope rather than an enclosing block. These differences affect which bindings are reachable during scope-chain lookup. `let` and `const` also have a temporal dead zone before their declarations are initialized.