My Javascript Execution Context Journey
Published: 2021-05-31 07:53:08

# Introduction
**Execution Context** is a concept if you understand it, will make it easier for you to understand more deeper concepts like :

* Scope
* Scope Chain
* Closure
* Event Loop

So in this article we will dive in this mysterious concept to understand what really happens under the hood in addition to digging a little bit deeper to know how `Execution Context` works with `Web APIs`, let's go.

# Execution Context
When a fragment of JavaScript code runs, it runs inside an execution context which is an abstract concept of an environment where the Javascript code is evaluated and executed By environment, we mean the value of this, variables, objects, and functions JavaScript code has access to at a particular time.

## When is an `Execution Context` created ?
There are three types of code that create a new execution context:

* **Global Execution Context (GEC)** This is the default or base execution context When a script executes for the first time, the JavaScript engine creates it. All of the global code ( which is not inside any function or object is executed inside the global execution context ). GEC cannot be more than one because only one global environment is possible for JS code execution as the JS engine is single threaded.

> Hint: In the Browser the **Global Execution Context** is created if there is no javascript script in the page or even when you do not have a single line of code in a .js file and load it, you will have the Global Execution Context created.

* **Function Execution Context** It is an Execution Context like similar **Global Execution Context** gets created when function is invoked, but instead of creating the global object, it creates the arguments object that contains a reference to all the parameters passed into the function:

* **Eval Execution Context** The underrated type in this Execution Context any code executed inside it also gets its own execution context, but because `eval` is underrated I will ignore it too and in the other hand it is also not recommended, so I will not discuss it here.

# Execution Context Stack 
When **Execution Context** is executing it is pushed into **Execution Contexts Stack** after it terminates, it popped off from the stack and this a whole process makes the javascript engine able to keep track off running function, or processes.

The way that **Execution Context Stack** works by can solve you the mysterious of how javascript is single threaded that is because you can't put multiple execution context in Execution Context Stack in the same time so you do one thing at run time

So the execution context stack can be conceptually represented as follows:
```
ExecutionContextStack [

  ExecutionStack <global> { ... }

]
```
When you execute your script the javascript engine creates a new Execution Context called **Global Execution Stack** we will examine it deeper later in this article, then it pushes it in our **Execution Context Stack**

# Execution Context Phases
Our **Execution Context** his life cycle walks through two phases:

## The Creation Phase
In this phase The execution context is created. which the JS engine is in the compilation phase and it just scans over the code to compile the code, it doesn’t execute any code and in our **Creation Phase** there is a lot of things happen.

1. LexicalEnvironment component is created.
2. VariableEnvironment component is created.

### Lexical Environment
According to ECMAScript 6 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
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:

Simply put, A **Lexical Environment** it's the internal Javascript Engine construct for let-defined variables. If you define a variable with let in a function , it is only visible within the function.

To keep all things simple let's put what we have just learned into code.
```javascript
let globalLet = 1;
const globalConst = 2;

function globalFunction () { ... }
```
```          
ExecutionContextStack [

  ExecutionContext <global> {

    lexicalEnvironment {
       globalLet : <uninitialized>,
       globalConst : <uninitialized>,
       globalFunction : <ref to "globalFunction" function>
    }

  }
]
```
Each Lexical Environment has three components:
* Environment Record
* Reference to the outer environment,
* This binding.

#### Environment Record
You can think of it like a dictionary in which declarations of variables and functions are stored within the lexical environment.

```javascript
let globalLet = 1;
const globalConst = 2;

function globalFunction () { ... }
```
```
ExecutionContextStack [

  ExecutionContext <global> {

    lexicalEnvironment {
 
       EnviromentRecord {
          globalLet : <uninitialized>,
          globalConst : <uninitialized>,
          globalFunction : <ref to "globalFunction" function>
       }
    }
  }
]
```

There are three type subclasses inside of the Environment Record:

* **Declarative environment record** — As its name suggests, it stores variables, modules and classes, in addition to function declarations, you can think about this concept as instantiations of something you know, like maps or tables to store declared objects in it.
* **Object environment record** — It is an **Environment Record** that associated with an object called `binding object` and for each of its properties a corresponding entry is created in the OER.

That is why you can access global variables such as `window.document` that is because `window` object is associated global execution context's object environment record any mutation on any on `window` applies on the record

```javascript
let globalLet = 1;
const globalConst = 2;

function globalFunction () { ... }
```
```
ExecutionContextStack [

  ExecutionContext <global> {

    lexicalEnvironment {
 
      EnviromentRecord {
        [[ type ]] : 'declarative'
        globalLet : <uninitialized>
        globalConst : <uninitialized>
        globalFunction : <ref to "globalFunction" function>
      }
      
      // binding with `window` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        globalFunction : <ref to "globalFunction" function>
      }
    }
  }
]
```

#### Reference to the Outer Environment
Every Environment Record has an `[[ outerEnv ]]` a reference to the outer environment ( the environment from which it was called ) to make the javascript engine able to look for variables inside the outer environment if they are not found in the current lexical environment

```javascript
let globalLet = 1;
const globalConst = 2;

function globalFunction (localArgument) {
  let localLet = 3;
  this.localProperty = 4;
}

new globalFunction(5);
```
```
ExecutionContextStack [

  ExecutionContext <globalFunction> {

    lexicalEnvironment {
 
      EnviromentRecord {
        [[ type ]] : 'declarative'
        arguments : { 0 : <ref to "localArgument" argument>, length : 1 }
        localLet : 3
      }
      
      // binding with `arguments` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        localArgument : undefined
      }
      
      // binding with `this` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        localProperty : undefined
      }
  
      this: <ref to "globalFunction" object>

    }

  }

  ExecutionContext <global> {

    lexicalEnvironment {
 
      EnviromentRecord {
        [[ type ]] : 'declarative'
        window : <ref to "window" object>
        globalLet : <unintialized>
        globalFunction : <ref to "globalFunction" function>
      }
      
      // binding with `window` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        globalFunction : <ref to "globalFunction" function>
        fetch : <built-in function>
        setTimeout : <built-in function>
      }
  
      this: <ref to "window" object>

    }
  
  }

]
```

#### This Binding
* In the global execution context the value of `this` refers to the global object ( in browsers, this refers to `window` object )
*  If it is called by an object reference, then the value of this is set to that object, otherwise, the value of this is set to the global object or undefined(in strict mode). For example:

`this` refers to the reference object and it's value depending on variety variables, so :
* In **Global Execution Context** it refers to the global object ( `window` in browser or `global` in node js )
* In **Functional Execution Context** it's referencing depends on the way that function call it. if it called by an object reference, then the value of `this` is set to that object. Otherwise, the value of `this` is set to the `window` object or will be of value `undefined` ( in strict mode )

```javascript
let globalLet = 0;

function globalFunction (localArgument) {
  let localLet = 1;
  this.localProperty = 2
}

new globalFunction(3);
```
```
ExecutionContextStack [

  ExecutionContext <globalFunction> {

    lexicalEnvironment {
 
      EnviromentRecord {
        [[ type ]] : 'declarative'
        arguments : { 0 : <ref to "localArgument" argument>, length : 1 }
        localLet : <unintialized>
      }
      
      // binding with `arguments` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        localArgument : undefined
      }
      
      // binding with `this` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        localProperty : undefined
      }
  
      this: <ref to "globalFunction" object>

    }

  }

  ExecutionContext <global> {

    lexicalEnvironment {
 
      EnviromentRecord {
        [[ type ]] : 'declarative'
        window : <ref to "window" object>
        globalLet : <unintialized>
        globalFunction : <ref to "globalFunction" function>
      }
      
      // binding with `window` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        globalFunction : <ref to "globalFunction" function>
        fetch : <built-in function>
        setTimeout : <built-in function>
      }
  
      this: <ref to "window" object>

    }
  
  }

]
```

### Variable Environment:
It's also a Lexical Environment so it has all the properties and components that defined above, the purpose beyond that is storing the variable (var) bindings only.
```javascript
var globalVariable = 0;
```
```
ExecutionContextStack [

  ExecutionContext <global> {

    lexicalEnvironment { . . . }

    variableEnvironment {
      
      // binding with `window` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        globalVariable : undefined
      }

      this: <ref to "window" object>
     
    }
  
  }

]
```

## Execution Phase
After **Creation Phase** our **Execution Context** walks through the **Execution Phase** to bind variable initializations, variable assignments, mutability and immutability checking, variable binding deletions, function call execution, etc.

```javascript
let globalLet = 0;

function globalFunction(localArgument) {
  var localVariable = 2;
  this.localProperty = 3
}

new globalFunction(4);
```
```
ExecutionContextStack [

  ExecutionContext <globalFunction> {

    lexicalEnvironment {
 
      EnviromentRecord {
        [[ type ]] : 'declarative'
        arguments : { 0 : <ref to "localArgument" argument>, length : 1 }
      }
      
      // binding with `arguments` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        localArgument : 4
      }
      
      // binding with `this` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        localProperty : 3
      }
  
      this: <ref to "globalFunction" object>

    }

  }

  ExecutionContext <global> {

    lexicalEnvironment {
 
      EnviromentRecord {
        [[ type ]] : 'declarative'
        window : <ref to "window" object>
        globalLet : 0
        globalFunction : <ref to "globalFunction" function>
      }
      
      // binding with `window` object
      EnviromentRecord {
        [[ type ]] : 'objective'
        globalFunction : <ref to "globalFunction" function>
        fetch : <built-in function>
        setTimeout : <built-in function>
      }
  
      this: <ref to "window" object>

    }
  
  }

]
```

At the end I advice you to read this article several times to fully understanding these all concepts

Thanks
# Sources

- [ stackoverflow - What really is a declarative environment record and how does it differ from an activation object? ](https://stackoverflow.com/questions/20139050/what-really-is-a-declarative-environment-record-and-how-does-it-differ-from-an-a)

- [ stackoverflow - Lexical environment and function scope ](https://stackoverflow.com/questions/12599965/lexical-environment-and-function-scope)

- [ stackoverflow - What is the scope of variables in JavaScript? ](https://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript?rq=1)

- [ stackoverflow - What's the difference between "LexicalEnvironment" and "VariableEnvironment" in spec ](https://stackoverflow.com/questions/40691226/whats-the-difference-between-lexicalenvironment-and-variableenvironment-in)

- [ medium - JavaScript/TypeScript: Execution vs. Lexical vs. Variable Environment ](https://medium.com/@bdov_/javascript-typescript-execution-vs-lexical-vs-variable-environment-37ff3f264831)

- [ 2ality - How do JavaScript’s global variables really work? ](https://2ality.com/2019/07/global-scope.html)

- [ medium - Lexical Environment — The hidden part to understand Closures ](https://amnsingh.medium.com/lexical-environment-the-hidden-part-to-understand-closures-71d60efac0e0)

- [ dev.to - JavaScript Execution Context ](https://dev.to/luigircruz/javascript-execution-context-38cn)

- [ stackoverflow - Lexical environment and function scope ](https://stackoverflow.com/questions/12599965/lexical-environment-and-function-scope)

- [ youtube - The Scope Chain, 🔥Scope & Lexical Environment | Namaste JavaScript Ep. 7 ](https://youtube.com/watch?v=uH-tVP8MUs8)

- [ medium - Execution context in JavaScript ](https://link.medium.com/1EcgFcs2ygb)

- [ youtube - How JavaScript Code is executed? ❤️& Call Stack | Namaste JavaScript Ep. 2 ](https://youtube.com/watch?v=iLWTnMzWtj4)

- [ green roots - Understanding JavaScript Execution Context like never before ](https://blog.greenroots.info/understanding-javascript-execution-context-like-never-before-ckb8x246k00f56hs1nefzpysq)

- [ javascript tutorial - Understanding JavaScript Execution Context By Examples ](https://javascripttutorial.net/javascript-execution-context)

- [ medium - Understanding Execution Context and Execution Stack in Javascript ](https://link.medium.com/cbeO1Tf3ygb)