Facebook Pixel

Lexical Scope vs Dynamic Scope in JavaScript

JS uses lexical (static) scope. Here is what that means and how it differs from dynamic scope.

Lexical Scope vs Dynamic Scope in JavaScript

JavaScript uses lexical scope (also called static scope). This is a fundamental design choice that affects how variables resolve.

Lexical (Static) Scope

The scope chain is determined by where functions are written in the source code. It is fixed at definition time and does not change based on where the function is called.

const x = 10; function foo() { console.log(x); } function bar() { const x = 99; foo(); } bar(); // 10, not 99 `` `foo` was written in the global scope, so it sees the global `x`. Calling it from `bar` does not give it access to `bar`'s `x`. ### Dynamic Scope (Hypothetical) In a dynamically-scoped language, `foo` would see the `x` of whoever called it. So `bar()` calling `foo()` would make `foo` log `99`. JavaScript does **not** work this way. ### Why Lexical Scope Matters - **Predictability**: you can read a function and know what it will access, without knowing all its callers. - **Performance**: the engine can determine scope at parse time, not run time. - **Closures**: lexical scope is what makes closures work. The function keeps its written-time scope chain. - **Tooling**: linters, type checkers, and IDEs can reason about scope without running the code. ### Exceptions in JS There are a few places where JavaScript feels dynamic: - **`this`**: determined by how the function is called, not where it is written (except for arrow functions, which are lexical). - **`eval`**: can modify the scope of its caller (in non-strict mode). Avoid it. - **`with`**: deprecated, created a dynamic scope. Removed in strict mode. These are exceptions, not the rule. Variable resolution (scope chain) is lexical. ### The Takeaway JavaScript uses lexical scope: the scope chain is fixed at write time based on where functions are defined. Calling a function from a different scope does not change what variables it can access. `this` is the main exception (determined at call time), but variable resolution is always lexical.

Lexical (static) scope. The scope chain is determined by where functions are written in the source code, not where they are called. Calling a function from a different scope does not give it access to that scope's variables.

In lexical scope, a function sees variables from where it was written. In dynamic scope, a function sees variables from whoever called it. JavaScript uses lexical scope; dynamic scope would make foo log the caller's x, not the writer's x.

Dynamically (by how the function is called), with one exception: arrow functions inherit this lexically from their enclosing scope. This is the main place where JS feels dynamic, but variable resolution (the scope chain) is always lexical.

It makes code predictable (you can read a function and know what it accesses), enables closures (the written-time chain persists), allows static tooling (linters, type checkers), and lets the engine optimize scope resolution at parse time.

In non-strict mode, eval can modify the caller's scope by introducing new variables. In strict mode, eval gets its own scope and cannot leak. Avoid eval; it is a security and performance risk and breaks lexical predictability.

Ready to master React completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.