Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does JavaScript's lexical environment maintain variables declarations within nested block scopes?

I've read a couple of more comprehensive articles on the execution context and now I am sort of confused and messed up in the head.

To keep the question as brief as possible avoiding long citations I better try to illustrate my mental model through an example focusing on details I can't get, so that you could correct me and point at the mistakes.

Here is an example:

var tomato = 'global tomato';

{
  let tomato = 'block tomato';
  console.log(tomato); // 'block tomato'
}

console.log(tomato); // 'global tomato'

So far, everything is clear. When JS engine created an execution context (global one in our case) var tomato declaration from the first line was placed into a Variable Environment while let tomato within a block scope went into a Lexical Environment. That explains how we ended up with 2 different tomatoes.

Now, let's add another tomato, like here:

var tomato = 'global tomato';

{
  let tomato = 'block tomato';

  {
    console.log(tomato); // ReferenceError: Cannot access 'tomato' before initialization
    let tomato = 'nested block tomato';
  }

  console.log(tomato); // won't reach here
}

console.log(tomato); // won't reach here

ReferenceError is no surprise. Indeed, we tried to access a variable before it's been initialized which is known as Temporal Dead Zone. And that nicely indicates that JS had already created another variable tomato within the most nested block. Also JS had been aware of this tomato being uninitialized at the moment we referenced it. Otherwise, it would have grabbed tomato from the outer scope which is equal to 'block tomato' without throwing any error. So let's fix the error and swap the lines, like this:

var tomato = 'global tomato';

{
  let tomato = 'block tomato';

  {
    let tomato = 'nested block tomato';
    console.log(tomato); // 'nested block tomato'
  }

  console.log(tomato); // 'block tomato' - still 'block tomato'. Nothing has been overwritten.
}

console.log(tomato); // 'global tomato'

What I wonder is how JavaScript manages this most nested block. Because by the time that execution reaches the line:

let tomato = 'nested block tomato';

the Lexical Environment of the execution context already contains the variable tomato which was initialized in the outer scope with the value of 'block tomato'. Assuming JS doesn't create a new execution context (with Lexical and Variable environments respectively) just for the blocks of code (that's only the case for function invocations and global script, right?) and obviously, it doesn't override variables in existing Lexical Environment with the ones having the same name but coming from the nested block scopes. As the last piece of code shows, where a brand new, independent variable was created to hold a value 'nested block tomato'.

Then the question is where exactly is this variable stored? I mean there is only one Lexical Environment for an execution context but we might create a numerous nested scopes declaring variables inside. I'm struggling to visualize where these variables would be stored and how this whole thing fit together.

like image 237
fekaloid Avatar asked Oct 24 '20 10:10

fekaloid


People also ask

What is lexical environment in JavaScript?

JavaScript lexical environment is a data structure that holds an identifier-variable mapping. Where identifier refers to the name of variables / functions, and variable is the reference to actual object. It also holds a reference to a parent lexical environment. Lexical Environment: Local Memory + Lexical Environment of its Parent

What is lexical scope in JavaScript?

Lexical scope is the definition area of an expression. In other words, an item's lexical scope is the place in which the item got created. Another name for lexical scope is static scope. The place an item got invoked (or called) is not necessarily the item's lexical scope.

What is the global scope in JavaScript?

Note: The global scope is the last link in JavaScript 's scope chain. How Does the Scope Chain Work? JavaScript's scope chain determines the hierarchy of places the computer must go through — one after the other — to find the lexical scope (origin) of the specific variable that got called. For instance, consider the code below:

What is the definition environment of a JavaScript expression?

A JavaScript expression’s definition environment determines the code permitted to access it. In other words, only code within an item's lexical scope can access it. Notice that the invocation of displayFullName () in the snippet above returned an Uncaught ReferenceError.


2 Answers

Assuming JS doesn't create a new execution context (with Lexical and Variable environments respectively) just for the blocks of code (that's only the case for function invocations and global script, right?)

That's an incorrect assumption.

See the specification:

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. Usually a Lexical Environment is associated with some specific syntactic structure of ECMAScript code such as a FunctionDeclaration, a BlockStatement, or a Catch clause of a TryStatement and a new Lexical Environment is created each time such code is evaluated.

The block statement creates a new lexical environment.

like image 50
Quentin Avatar answered Oct 21 '22 16:10

Quentin


In ECMAScript, lexical scopes can be nested.

I mean there is only one Lexical Environment for an execution context but we might create a numerous nested scopes declaring variables inside.

No, there is one Lexical Environment for … well … each Lexical Environment. ("Scope" is just a different term for "Environment" after all.)

The specification does not force the implementor to implement this in any specific way. A typical way could be to have linked list of environments.

like image 4
Jörg W Mittag Avatar answered Oct 21 '22 18:10

Jörg W Mittag