Monday, December 10, 2018

Execution Context

Execution context (EC) is defined as the environment in which JavaScript code is executed. By environment I mean the value of this, variables, objects, and functions JavaScript code has access to, constitutes it’s environment.

Execution context in JavaScript are of three types:

Global execution context (GEC): This is the default execution context in which JS code start it’s execution when the file first loads in the browser. All the global code are executed inside global execution context. In the browser context, if the code is executing in strict mode value of this is undefined else it is window object. Global execution context cannot be more than one because only one global environment is possible for JS code execution.
Functional execution context (FEC): Functional execution context is defined as the context created by the execution of code inside a function. Each function has it’s own execution context. It can be more than one. Functional execution context have access to all the code of global execution context. While executing global execution context code, if JS engine finds a function call, it creates a new functional execution context for that function.

Eval: Execution context inside eval function.

JavaScript engine creates the execution context in the following two stages:

1. Creation phase
2. Execution phase


Creation phase is the phase in which JS engines has called a function but it’s execution has not started. In the creation phase, JS engine is in the compilation phase and it scans over the function to compile the code.

In creation phase, JS engine performs the following task:

1. Creates the Activation object or the variable object: Activation object is a special object in JS which contain all the variables, function arguments and inner functions declarations information. As activation object is a special object it does not have the dunder proto property.
2. Creates the scope chain: Once the activation object gets created, JS engine initializes the scope chain which is a list of all the variables objects inside which the current function exists. This also includes the variable object of global execution context. Scope chain also contains the current function variable object.
3. Determines the value of this: After the scope chain, JavaScript engine initialize the value of ‘this’.

Let’s understand how JavaScript engines creates the activation object with an example

function funA (a, b) {
  var c = 3;
  
  var d = 2;
  
  d = function() {
    return a - b;
  }
}


funA(3, 2);

Just after funA is called and before code execution of funA starts, JS engine creates an executonContextObj for funcA which can be represented as shown below:
    executionContextObj = {
 variableObject: {}, // All the variable, arguments and inner function details of the funA
 scopechain: [], // List of all the scopes inside which the current function is
 this // Value of this 

  


Activation object or variable object contains argument object which have details about the arguments of the function.

It will have a property name for each of the variables and functions which are declared inside the current function

Activation object or the variable object in our case will be as shown below:
  variableObject = {
  argumentObject : {
    0: a,
    1: b,
    length: 2
  },
  a: 3,
  b: 2
  c: undefined,
  d: undefined then pointer to the function defintion of d
}

}
  
  


ArgumentObject: JS engines will create the argument object as shown in the above code. It will also have the length property indicating the total number of arguments in the function.
Now, for each variable in the function, JS engine will create a property on the Activation object and will initialize it with undefined. As arguments are also variables inside the function, they are also present as a property of the argument object.
If the variable already exists as a property of the argument object JS engine will not do anything and will move to the next line.
When JS engines encounters a function definition inside the current function, JS engine will create a new property by the name of the function. Function definitions are stored in heap memory, they are not stored in the execution context stack. Function name property points to it’s definition in the heap memory.
Hence, first d will get the value of undefined as it is a variable but when JS engine encounters a function with the same name it overrides it’s value to point it to the definition of function d stored in the heap.

After this JS engines will create the scope chain and will determine the value of this.

Execution phase:

In the execution phase, JS engines will again scan through the function to update the variable object with the values of the variables and will execute the code.

After the execution stage, variable object will look like this:
  variableObject = {
  argumentObject : {
    0: a,
    1: b,
    length: 2
  },
  a: 3,
  b: 2,
  c: 3,
  d: undefined then pointer to the function defintion of d
}
  

Scope Chain:

Scope chain is a list of all the variable objects of functions inside which the current function exists. Scope chain also consists of the current function execution object.

Consider the below code:

a = 1;

var b = 2;

cFunc = function(e) {
  var c = 10;
  var d = 15;
  
  console.log(c);
  console.log(a); 
  
  function dFunc() {
    var f = 5;
    console.log(f)
    console.log(c);
    console.log(a); 
  }
  
  dFunc();
}

cFunc(10);


Here, when function cFunc is called from the global execution context, scope chain of cFunc will look like this

Scope chain of cFunc = [ cFunc variable object, 
                         Global Execution Context variable object]
When dFunc is called from cFunc, as dFunc is inside cFunc, dFunc’s scope chain consists of dFunc variable object, cFunc variable object and global execution context variable object.

Scope chain of dFunc = [dFunc variable object, 
                        cFunc variable object,
                        Global execution context variable object]
When we try to access f inside dFunc, JS engines checks if f is available inside dFunc’s variable object. If it finds f’s value it console.log f’s value.

When we try to access variable c inside dFunc, JS engines checks if c is available inside dFunc’s variable object. If the variable is not available, then it will move to cFunc variable object.

As variable c is not available inside dFunc’s variable object, JS engines moves to cFunc’s variable object. As c is available on cFunc variable object, it will console.log c’s value.

When we try to log a’s value inside dFunc, JS engines will check if a is available inside dFunc’s variable object. If a is not available inside dFunc’s variable object, it will move to the next item in scope chain i.e. cFunc’s variable object. JS engines will check if cFunc’s variable object as variable a. Here, variable a is not available on cFunc’s variable object hence, it will check the next items in dFunc’s scope chain i.e. global execution context variable object. Here a is available on dFunc’s variable object and it will console a’ s value.

Similarly, in case of cFunc, JS engine will find variable a’s value from global execution object.

cFunc does not know that variable f exists. Hence if we try to access f from cFunc it will give error. But, dFunc function has access c and d variable using the scope chain

Closures can be explained using the scope chain context in JavaScript.

https://hackernoon.com/execution-context-in-javascript-319dd72e8e2c

No comments:

Followers

Link