71

Is lexical environment and scope in javascript one and the same thing?

Aljoša Srebotnjak
  • 1,311
  • 2
  • 12
  • 13

3 Answers3

77

Giving the answer based on what I have just learned from 'Secrets of the JavaScript Ninja, 2/e':

They are different concepts but related: we need to define a related concept - Execution Context & it's stack to understand.

Execution Context & Execution Context stack. Execution context is the internal JavaScript construct that tracks execution of a function or the global code. The JS engine maintains a stack data structure - execution context stack or call stack, which contains these contexts. The global execution context stays at the bottom of this stack. A new execution context is then created and pushed to the stack when execution of a function begins. A particular execution context tracks the pointer where statement of the corresponding function is being executed. An execution context is popped from the stack when the corresponding function's execution is finished.

Lexical Environment is the internal JS engine construct that holds identifier-variable mapping (here identifier refers to the name of variables/functions, and variable is the reference to actual object (including the function type object) or primitive value). A lexical environment also holds a reference to a parent lexical environment.

Now, for every execution context:

  1. a corresponding lexical environment is created and
  2. if any function is created in that execution context, reference to that lexical environment is stored at the internal property ([[Environment]]) of that function. So, every function tracks the lexical environment related to the execution context it was created in.

Every lexical environment tracks its parent lexical environment (that of parent execution context). As a result, every function has a chain of lexical environments attached to it.

Note: in JS a function is an object. Creating a function with a statement means creating an object of type Function. So, like other objects, a function can hold properties both internal and user defined.

Scope is a language agnostic concept that refers to the visibility of variables or functions to the executing code. In JS, a variable or function is visible to the executing code if it is there in the current lexical environment or in the lexical-environment-chain of the enclosing function. In case of global code, the chain does not exist.

Hope, you understand now...

Note: similar to the function, via the introduction of let and const in es6, when a block begins to execute (if block, for loop block etc), a new lexical environment is also created with the parent function's lexical environment as parent.

Peter David Carter
  • 2,548
  • 8
  • 25
  • 44
adnan2nd
  • 2,083
  • 20
  • 16
  • I wonder if this reply is adapt also for ES6 (the book you make reference was published before the ES6 release) – marco May 03 '19 at 13:40
  • ES6 was finalized in June 2015, and the book (2nd edition) was published in September 2016 – adnan2nd May 05 '19 at 14:09
  • 1
    This is interesting for me what is different [[Environment]] and [[Scope]] internal properties? – Murad Sofiyev Aug 12 '19 at 16:52
  • 4
    @MuradSofiyev, there is no internal [[Scope]] property. It was mentioned in [ECMAScript 5.1](https://www.ecma-international.org/ecma-262/5.1/index.html#sec-13.2) however, from [ECMAScript 6th](https://www.ecma-international.org/ecma-262/6.0/index.html#sec-functioninitialize) on it was replaced with [[Environment]] internal property. So I suppose they are mostly the same. – ansavchenco Mar 19 '20 at 09:51
  • isn't more accurate to say that the function's lexical environment tracks it's parent lexical environment ? and not the function tracks it's parent lexical environment because all the magic of the scope chain is the chain of lexical environments – Nadav Shlush Sep 22 '21 at 16:33
33

Lexical Environment is the environment of the function where it is written. That is, the static order/place where it is situated, regardless from where it is called from.

Scope of a variable/function is basically the locations from where a variable is visible/accessible.

Execution context is the status of the execution stack at any point during runtime. That is the current execution context.

poushy
  • 1,114
  • 11
  • 17
  • 2
    If I had not read the other answers before this one, it would have been a little confusing, but I think this answer best sums up an easy way to understand and differentiate the Lexical Environment from the Scope. – Hawkeye Apr 10 '19 at 21:00
31

Here's what the spec says about lexical environments:

A Lexical Environment is a specification type used to define the association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code. A Lexical Environment consists of an Environment Record and a possibly null reference to an outer Lexical Environment.

Based on that, I would say yes, that's what people are usually talking about when they say "scope".

Although it could probably be argued that a "scope" is actually defined as a "Declarative Environment Record":

Each declarative environment record is associated with an ECMAScript program scope containing variable and/or function declarations. A declarative environment record binds the set of identifiers defined by the declarations contained within its scope.

If you think of a "scope" as a thing that contains bindings between identifiers and values, then the 2nd definition probably fits better. If you think of it as something that is aware of its ancestor scopes, then the first definition fits better.

Edit: and a third option is "Execution Context".

James Allardice
  • 164,175
  • 21
  • 332
  • 312
  • The second definition refers to a "scope", so cannot be a definition of "scope" itself. – OrangeDog Apr 30 '16 at 17:46
  • Yes it can. The question is about "programming" scope. The second definition uses the "normal" (dictionary if you will) English definition of the word scope. – zenw0lf Jan 05 '17 at 14:39
  • 1
    I think it is correct that the scope of a variable/function is indeed the *current execution context*'s *Lexical Environment*. See "9.2.4 Function Initialize" (http://www.ecma-international.org/ecma-262/8.0/#sec-functioninitialize): "*...Lexical Environment specified by Scope*". That's a pretty solid hint. – Magnus Jul 26 '18 at 22:13