Lexical Environment-the hidden part to understand Closures
Tags: javascript, webdev, closures, lexicalenvironment
Published: 2019-07-07 09:19:09


**Closures** can be a daunting concept when you are new to JavaScript world. Scouring the internet will give you tons of definition about what *closure* is. But I have felt that mostly these definitions are vague and don’t explain the fundamental cause of their existence.

Today we will try to demystify some of these concepts which are part of the [ECMAScript 262 specs](https://tc39.github.io/ecma262), including **Execution** **Context**, **Lexical Environment**, and **Identifier Resolution**. Additionally, we will learn that because of these mechanisms, all *functions* in ECMAScript are *closures*.

I will explain the terminology first and then show you some code examples explaining how all these pieces work together. This will help to solidify your understanding.


## Execution Context
JavaScript interpreter creates a new context whenever it’s about to execute a function or script we’ve written. Every script/code starts with an execution context called a global execution context. And every time we call a function, a new execution context is created and is put on top of the execution stack. The same pattern follows when you call the nested function which calls another nested function:

![alt text](https://thepracticaldev.s3.amazonaws.com/i/ttxfknmndl6hozijk0gj.png "execution context")

Let’s see what happens when our code is executed as shown in the picture above:

  * A global execution context is created and placed at the bottom of the execution stack.
  * When the bar is invoked, a new bar execution context is created and is put on top of the global execution context.
  * As, bar calls to a nested function foo, a new foo execution context is created and is placed on top of the bar execution context.
  * When foo returns, its context is popped out of the stack and flow returns to the bar context.
  * Once bar execution is finished, the flow returns back to the global context and finally, the stack is emptied.

Execution stack works on a LIFO data structure way. It waits for the topmost execution context to return before executing the context below.

Conceptually, Execution context has a structure which looks like the following:

```javascript
  // Execution context in ES5
ExecutionContext = {
  ThisBinding: <this value>,
  VariableEnvironment: { ... },
  LexicalEnvironment: { ... }
}
```
Don’t worry if structure looks intimidating. We will look at these components shortly. The key point to remember is that every call to execution context has two stages: **Creation Stage** and **Execution Stage**. Creation Stage is when the context is created but not invoked yet.

A few things happen in the *creation* stage:

  * **VariableEnvironment** component is used for the initial storage for the variables, arguments and function declarations. The var declared variables are initialized with the value of undefined.
  * The value of *This* is determined.
  * **LexicalEnvironment** is just the copy of VariableEnvironment at this stage.

Upon *execution* stage:

  * Values are assigned.
  * LexicalEnvironment is used to resolve the bindings.

Now, let’s try to understand what is a lexical environment.

## Lexical Environment
According to ECMAScript specification 262 (8.1):

> A Lexical Environment is a specification type used to define the association of [Identifiers](https://tc39.github.io/ecma262/#prod-Identifier) to specific variables and functions based upon the lexical nesting structure of ECMAScript code.

Let’s try to simplify a few things here. A lexical environment consists of two main components: the **environment** record and a **reference** to the outer (parent) lexical environment:

```javascript
var x = 10;

function foo(){
  var y = 20;
 console.log(x+y); // 30
}

// Environment technically consists of two main components:
// environmentRecord, and a reference to the outer environment

// Environment of the global context
globalEnvironment = {
  environmentRecord: {
    // built-ins
    // our bindings:
    x: 10
  },
  outer: null // no parent environment
};

// Environment of the "foo" function
fooEnvironment = {
  environmentRecord: {
    y: 20
  },

  outer: globalEnvironment
};
```

Visually it will look like this:

![alt text](https://thepracticaldev.s3.amazonaws.com/i/drbm1oooovq9apv5fyn3.png "LexicalEnvironment")

As you can see when trying to resolve the identifier “*y*” in the foo context, the outer environment (global) is reached out. This process is called identifier resolution and happens on running execution context.

Now, armed with this knowledge of Environments, let’s get back to the structure of Execution context and see what’s happening there:

  * **VariableEnvironment**: Its *environmentRecord* is used for the initial storage for the variables, arguments and function declarations, which later is filled on entering the context activation stage.

```javascript
function foo(a) {
  var b = 20;
}
foo(10);

// The VariableEnvironment component of the foo function
//context at creation stage
fooContext.VariableEnvironment = {
  environmentRecord: {
    arguments: { 0: 10, length: 1, callee: foo },
    a: 10,
    b: undefined
  },
  outer: globalEnvironment
};

// After the execution stage, the VE envRec
// table is filled in with the value
fooContext.VariableEnvironment = {
  environmentRecord: {
    arguments: { 0: 10, length: 1, callee: foo },
    a: 10,
    b: 20
  },
  outer: globalEnvironment
};
```

  * **LexicalEnvironment**: Initially, it’s just a copy of the VariableEnvironment. On the running context, it is used to determine the binding of an identifier appearing in the context.

Both *VE* and *LE* by their nature are lexical environments, i.e both statically(at creation stage) captures the outer bindings for inner functions created in the context. This mechanism gives rise to closures.

> Capturing the outer binding statically for inner functions give rise to the formation of closures.

## Identifier Resolution aka Scope chain lookup

Before understanding the closure, let’s understand how the scope chain is created in our execution context. As we saw earlier, each execution context has *LexicalEnvironment* which is used for identifier resolution. All the local bindings for the context are stored in the environment record table. If identifiers are not resolved in the current environmentRecord, the resolution process will continue to the outer (parent) environment record table. This pattern will continue until the identifier is resolved. If not found, a *ReferenceError* is thrown.

This is very similar to the prototype lookup chain. Now, the key to remember here is that *LexicalEnvironment* captures the outer binding **lexically** (statically) on context creation stage and used as it is on the running context (execution stage).

## Closures

As we saw in the previous section that upon function creation stage, statically saving of outer binding in the *LexicalEnvironment* of inner context gives rise to closures regardless of whether a function will be activated later or not. Let see that in an example:

### Example 1:

```javascript
var a = 10;
function foo(){
  console.log(a);
};
function bar(){
  var a = 20;
  foo();
};
bar(); // will print "10"
```


The *LexicalEnvironment* of foo captures the binding “*a*” at creation time, which was 10. So, when *foo* is invoked later (at execution stage), the “*a*” identifier is resolved with a value of *10* but not *20*.

Conceptually, the identifier resolution process will look something like this:

```javascript
// check for binding "a" in the env record of "foo"
-- foo.[[LexicalEnvironment]].[[Record]] --> not found

// if not found, check for its outer environment


--- global[[LexicalEnvironment]][[Record]] --> found 10
// resolve the identifier with a value of 1
```

![alt text](https://thepracticaldev.s3.amazonaws.com/i/dhz0iwu01xecfftd3dj3.png "execution context")

### Example 2

```javascript
function outer() {
 let id = 1;

 // creating a function would statically captures
 // the value of 'id' here
 return function inner(){
  console.log(id);
  }
};

const innerFunc = outer();
innerFunc(); // prints 1;
```

When the *outer* function returns, its execution context is popped out from the execution stack. But when we invoke the *innerFunc()* later, it still manages to print out the correct value because *LexicalEnvironment* of inner function statically captured the “*id*” binding of its outer (parent) environment when it was created.

```javascript
// check for binding "id" in the env record of "inner"
-- inner.[[LexicalEnvironment]].[[Record]] --> not found
// if not found, check for its outer environment (outer)
--- outer[[LexicalEnvironment]][[Record]] --> found 1
// resolve the identifier with a value of 1
```

![alt text](https://thepracticaldev.s3.amazonaws.com/i/b9sleb9ywpegmziv9oxb.png "closure example 2")

---

## Conclusion
 * Execution context stack follows **LIFO** data structure.
 * There’s one Global context where our code/script is executed.
 * Call to a function creates a new execution context. If it has a nested function call, a new context is created and is put on top of its parent context. When the function finishes executing, it gets popped out of the stack and flow returns back to the context below in the stack.
 * Lexical Environment has two main components: **environmentRecord** and **reference** to the outer environment.
 * **VariableEnvironment** and **LexicalEnvironment** both statically captured the outer binding for inner functions created in the context.
All functions at the **creation** stage statically(lexically) captures the outer binding of their parent environment. This allows the nested function to access the outer binding even if the parent context is wiped out from the execution stack. This mechanism is the foundation of closures in JavaScript.

I hope this article was fun to read and wasn’t overwhelming. If you liked the article, a few ❤️ will definitely make me smile. Happy coding 😊.