What is an execution context?

The environment in which Javascript code is executed is called the execution context.

The type of execution context

  1. Global execution context: There can be only one global execution context in a program. A global variable is created in the global context (window in the browser context) and this points to the global variable.

  2. Function execution context: There can be any number of function execution contexts. A function execution context is created when a function is called, and each function has its own execution context.

  3. Eval function execution context: Code executed within the eval function also has its own execution context (not often used).

Execution stack

LIFO is a LIFO (LIFO) data structure used to hold the execution context generated while the code is running.

Code examples:

let a = 'hello world! '
function b () {
    console.log('b')
    c()
}
function c () {
    console.log('c')
}
b()
Copy the code

The order of execution in the stack is:

Execution context

The execution context is divided into two phases: the creation phase and the execution phase.

Create a stage

Before the Js code executes, the execution context goes through the create phase, creating lexical environment components, variable environment components, and the This binding.

  • Lexical environment components

    In ES6 documentation, a lexical environment is a canonical type that defines the association of identifiers and concrete variables and functions based on the lexical nesting structure of ECMAScript code. A lexical environment consists of an environment logger and a null value that may reference an external lexical environment.

    Simply put, the lexical environment is a mapping of identifiers: variables. An identifier refers to the name of a variable or function, which can be raw or reference type data in JS.

    As you can see from the ES6 documentation’s definition of a lexical environment, there are two components in a lexical environment:

    • Environment logger: Holds variables (let and const declarations) and function declarations
    • References to external environments: lexical environments that have access to the parent (scope)

    There are two types of lexical environment: global environment and functional environment

    • Global context: In a global context, the lexical context is the global lexical context. The global lexical environment has no external lexical environment reference, so the external lexical environment reference is NULL. It has built-in properties and methods (Array, Object, Math, etc.), as well as user-defined global variable and function declarations, and this points to global objects.

    • Function context: Variables defined in a function are stored in the context logger, and references to the external lexical context can be either the global lexical context or the lexical context of the external function that contains this function.

    Environment loggers also come in two types:

    • Object environment logger: The environment logger in the global lexical environment, which holds variable and function declarations defined in the global context.
    • Declarative environment logger: An environment logger in a functional lexical environment that holds variables defined in the function context, function declarations, and arguments objects passed to the function (index-parameter mapping, parameter length).
  • A variable environment component is a lexical environment component that has all the properties of a lexical environment component. In ES6, the difference between a lexical environment and a variable environment is that the lexical environment holds variables declared by functions and let and const, while the variable environment holds variables declared by var.

  • This binding

    If the current function is called as an object method or this is bound with call, apply, bind, etc., then this is set to that object, otherwise it defaults to a global object call

During the execution context creation phase, variables defined by var are initialized to undefined, and variables defined by let and const are not initialized. This is called declaration promotion. Variables defined by var can be accessed prior to declaration, but variables defined by let and const will report an error.

Execution phase

Enter the execution phase of the execution context, complete the assignment of variables, and finally execute the code.

Execution context flow

  1. The program starts and the global execution context is created

    1. Create a global execution context lexical environment

      • Create object environment loggers that handle variable and function declarations defined by let and const in the global context

      • Creates an external environment reference with a value of null

    2. Create the global execution context variable environment

      • Create an object environment logger that handles variables defined by var in the global context, with an initial value of undefined to form a declaration boost

      • Creates an external environment reference with a value of null

    3. Make this binding value a global object (window in the browser)

  2. The function is called, and the function execution context is created

    1. Create a lexical environment for the function execution context

      • Create declarative environment loggers that handle variables defined by lets and const in functions, function declarations, and arguments objects passed to functions (index-parameter mapping, parameter length)

      • Create an external environment reference with a value of a global object, or a parent lexical environment (scope)

    2. Create a function execution context variable environment

      • Create a declarative environment logger that handles variables defined by var in the function, starting with undefined to form a declarative lift

      • Create an external environment reference with a value of a global object, or a parent lexical environment (scope)

    3. Determine the this binding value

  3. Enter the execution context execution phase

    1. At this stage, the variables are assigned corresponding values, and then the code is executed

Use pseudocode to aid understanding

let g1 = 1
const g2 = 2
var g3

function func(p1, p2) {
  let f1 = 1
  var f2 = 2
  return p1 + p2
}

g3 = func('hello '.'world')
Copy the code

Execution context structure

GlobalExectionContext = {

  ThisBinding: <Global Object>,

  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      g1: < uninitialized >,
      g2: < uninitialized >,
      func: < function >
    }
    outer: <null>
  },

  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      g3: undefined,
    }
    outer: <null>
  }
}

FunctionExectionContext = {
  ThisBinding: <Global Object>,

  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      arguments: {0: 'hello ', 1: 'world', length: 2},
      f1: < uninitialized >
    },
    outer: <GlobalLexicalEnvironment>
  },

  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      f2: undefined
    },
    outer: <GlobalLexicalEnvironment>
  }
}
Copy the code

The summary

  • When a program starts running, it becomes the global execution context. The function execution context is created when the function is called

  • The execution context is managed by the execution stack, which is a LIFO (LIFO) data structure. The global context is always at the bottom of the execution stack. When a function is called to generate the execution context, the context will be pushed to the top of the execution stack. After the function is executed, the context will be ejected from the execution stack, and the execution flow will reach the next context in the execution stack.

  • Variable and function declarations defined by var have declaration enhancement.

  • When a variable is found, if the current execution context does not exist, the context lookup is performed at the parent level (the parent lexical environment at the time of the function declaration), all the way to the global object. The linked list of these execution contexts is the scope chain.

Relevant reference

  • Understand the execution context and execution stack in JavaScript

  • Interviewer: Tell me about the execution context