Closure-Lexical Environment-Variable Environment

Nov 5, 2021
5 min read

What's the closure? While preparing for the interview, you must have checked this question or should say that you should already know this question. The closure is really important in the functional programming world. You can access the outer scope of the function from an inner function. In other words, a closure is a bundle of a function and references to the surrounding state. The surrounding state means the lexical environment. Simply put it is in such a way that whenever the function is created, the closure is also created.


The interesting point here is that the anonymous function that is returning is not alone, but is taking a and b variables along with it. A single function is not executed, a record is executed. The lexical scope of the function also lives with it, i.e. overall closure is the return.

Let us take some examples:

function IncreaseNumber() {

// Local “free” variable that ends up within the closure

var num = 1;

function fNumber() {

console.log(num);

}

num++;

return fNumber;

}

var number = IncreaseNumber();

number(); // 2

The function fNumber does not have a local variable of its own. But it has access to the external function, due to which the value will be logged to the console after the num is incremented.

function fIntro() {

var fStore = function() { console.log(strWord); }

// Local variable that ends up within the closure

var strWord = 'Hi, I am Hamid!';

return fStore;

}

var sayHi = fIntro();

sayHi(); // ‘Hi, I am Hamid!’

Although strWord is defined after the anonymous function, it was in scope at the time of the function creation. Hence it is available while executing the anonymous function.

We move to a higher level now.

Going to a higher level means we want to know what is actually happening in the background. Because the variables remain accessible in the enclosing function(s), even when the same enclosing function has also returned. To understand its depth, we have to turn to an abstract concept called Execution context.

In JavaScript, one command is run at a time i.e. JavaScript is single-threaded. Javascript will only handle one execution context at a time.

Browsers maintain execution context through the stack. Whatever you push into the stack, the last one will be executed first. Stack is a LIFO data structure: Last In First Out. An insertion or deletion can occur only at the top of the stack.

The top item in the stack is the current or running execution context.

Sometimes it may happen that one running execution context is suspended and another execution context starts running. That means the running execution context does not need to terminate for a different execution context to run.

The running execution context may also get suspended. The suspended execution context subsequently resumes where it left off. Thus we will have a bunch of execution contexts running one after the other. Some of these pause in the middle and resume after a while.

There must be some way to track the states so that we can manage the orders and execution of these contexts. The ECMAScript spec provides you with the state components which allow you to track the progress of the code in each context:

Code evaluation state: It evaluates the code that is associated with the execution context. It is needed to perform code evaluation, suspend and resume.

Function: Execution context evaluates the function object.

Realm: A set of intrinsic objects. Realm is created after the Execution Context Stack is created. Realm provides access to the global environment. The Realm is created before the code is executed and is linked to all code related to the surrounding agent.

Lexical Environment: A reference to the outer environment.

Variable Environment: This lexical environment is just another fancy representation of local memory. In this, EnvironmentRecord holds bindings created by VariableStatements within this execution context.

The most important point of all this is the "Lexical Environment Variable" as it explicitly states that it resolves "Identifier references" that are created by the code in its executable context. You can consider “identifiers” as variables.

The lexical environment manages the data within the code. It can be said that it gives meaning to identifiers.

Console.log(x/70);

Whenever x will get the value, the code will get the meaning and that would be possible through its Environment Record.

The Lexical Environment consists of an environment record that contains all identifiers and bindings. Each Lexical Environment has its own Environment record.

The inner environment refers to the outer environment that surrounds it. And the outer can have another outer environment. That is, one outer environment can have many other inner environments. The global environment is that lexical environment that has no outer environment. You will be definitely thinking about the layers of an onion.

An environment can access the parent environment and the parent environment can also access its parent environment and so on. Thus, each environment has scope to access the set of identifiers and the environments forming a complete hierarchical chain is called a scope chain.

We are not off-topic, it was necessary to cover everything to get close to understanding closure.

A function has an execution context whose environment gives meaning to the function's variables and references to the parent environment. A reference to the parent environment makes all variables in the parent scope accessible to all internal functions. However, it does not matter whether the inner function(s) are called outside or inside the scope in which they were created.


You get 125 as the function test is invoked. 125 is actually the return value that is obtained by invoking the bar function. The bar function can access the free variable y even after foo returns bar because it has a reference to y through its outer environment. This outer environment is basically foo's environment. bar function can also access x as the foo has access to the global environment. This is called "scope-chain lookup".

Final Words

Execution context is an abstract concept that the ECMAScript specification uses to track the runtime evaluation of code. There is only one execution context for the code to be executed at any given point in time.

Each execution context has a Lexical environment containing identifier bindings(i.e. variables and their associated values) and a reference to the outer environment.

The set of identifiers that each environment has access to is called the scope. If these scopes are nested, a hierarchical chain is formed called the scope chain.

Each function has its own execution context which includes a lexical environment and this lexical environment gives meaning to the variables within that function as well as the reference to its parent environment. And when the function has full knowledge of this environment because the function has a reference to this environment, it is called closure.

As soon as the enclosing outer function is called, it creates a closure. It is not necessary to return the inner function to create closure.

A closure is defined statically by its location within the source code, so its scope is lexical.