Skip to content

JavaScript Advanced (IV)—Execution Context

About 1098 wordsAbout 4 min

javascript

2020-02-12

Execution context

The execution context is an abstract concept of the environment ** where the JavaScript code is parsed ** and **execute **. Any code for JavaScript is executed in the execution context.

type

JavaScript has three types of execution contexts:

  • Global execution context

The default execution context, or the underlying execution context. Any code that is not inside a function is in the global execution context. The global context performs two things:

  • Create a global window object (in the browser environment).
  • Set the value of this equals the global window object.

A program will only have one global execution context.

  • Function execution context

Whenever a function is executed, a new execution context is created for the function. Each function has its own execution context and is created when the function is executed. Function contexts can have as many as possible. Whenever a function execution context is created, it will perform a series of steps in the defined order.

  • eval function execution context

The code executed inside the eval function will also have its own execution context.

Create an execution context

The creation execution context is mainly divided into two stages: Creation phase and Execution phase.

Creation phase

During the creation stage, three things will be done:

  • Decision of this value, i.e. This binding
  • Create lexical environment components
  • Create variable environment components

This binding

  • Global execution context

In the global execution context, the value of this points to the global object. (In the browser, this refers to the Window object).

  • Function execution context

In the function execution context, the value of this depends on how the function is called. If it is called by a reference object, then this is set to that object, otherwise the value of this is set to global object or undefined (in strict mode).

let foo = {
  bar: function () {
    console.log(this)
  },
}

// 'this' refers to 'foo', because 'baz' is called by the object 'foo'
foo.bar()

let bar = foo.baz

// 'this' points to the global window object because no reference object is specified
bar()

Lexical environment

ECMAScript Standard

Lexical environment is a canonical type that defines the association between identifiers and specific variables and functions based on lexical nested structures of ECMAScript code. A lexical environment consists of an environment recorder and a possible null value that references an external lexical environment.

A lexical environment is a structure that holds an identifier-variable map.

Tips

The identifier here refers to the name of the variable/function, which is a reference to the actual object [including the function type object] or the original data.

There are two components inside the lexical environment: (1) Environment recorder and **(2) a reference to an external environment.

  • Environment logger is the actual location where variables and function declarations are stored.
  • Reference to external environment means it can access its parent lexical environment (scope).

There are two types of lexical environments:

  • Global Environment (in the global execution context) is a lexical environment without external environment references. The external environment reference to the global environment is null. It has built-in Object/Array/, prototype functions in the environment logger (associated global objects, such as window objects), and any user-defined global variables, and the value of this points to the global object.
  • In the function environment**, user-defined variables inside the function are stored in the environment logger. And the referenced external environment may be the global environment, or any external function that contains this internal function.

There are two types of environment loggers:

  • Declarative Environment Recorder: Stores variables, functions and parameters.
  • Object Environment Recorder: Used to define the relationship between variables and functions that appear in the global context.

It can be seen that:

  • In the global environment, the environment logger is an object environment logger.
  • In function environment, the environment recorder is a declarative environment recorder.

Tips

For function environments, the declarative environment logger also contains a arguments object passed to the function (this object stores the mapping of indexes and parameters) and length of the parameters passed to the function.

Use pseudo-code to describe the lexical environment, roughly as follows:

GlobalExecutionContext = {
 LexicalEnvironment: {
 EnvironmentRecord: {
 Type: "Object",
 // Bind the identifier here
 }
 outer: <null>
 }
}

FunctionExecutionContext = {
 LexicalEnvironment: {
 EnvironmentRecord: {
 Type: "Declarative",
 // Bind the identifier here
 }
 outer: <Global or outer function environment reference>
 }
}

Variable environment

Variable Environment is also a lexical environment whose environment recorder holds the binding relationship created by the variable declaration statement in the execution context.

Variable Environment has all the properties of the lexical environment defined above.

In ES6, a difference between the lexical environment and the variable environment is that the former is used to store function declarations and variables (let and const) bindings. The latter is only used to store var variable binding.

Sample code:

let a = 20
const b = 30
var c

function multiply(e, f) {
  var g = 20
  return e * f * g
}

c = multiply(20, 30)

Sample code Execute context pseudocode:

GlobalExectionContext = {

 ThisBinding: <Global Object>,

 LexicalEnvironment: {
 EnvironmentRecord: {
 Type: "Object",
 // Bind the identifier here
 a: < uninitialized >,
 b: < uninitialized >,
 multiply: < func >
 }
 outer: <null>
 },

 VariableEnvironment: {
 EnvironmentRecord: {
 Type: "Object",
 // Bind the identifier here
 c: undefined,
 }
 outer: <null>
 }
}

FunctionExectionContext = {
 ThisBinding: <Global Object>,

 LexicalEnvironment: {
 EnvironmentRecord: {
 Type: "Declarative",
 // Bind the identifier here
 Arguments: {0: 20, 1: 30, length: 2},
 },
 outer: <GlobalLexicalEnvironment>
 },

 VariableEnvironment: {
 EnvironmentRecord: {
 Type: "Declarative",
 // Bind the identifier here
 g: undefined
 },
 outer: <GlobalLexicalEnvironment>
 }
}

Warning

The function execution context is created only when the function multiply is called.

illustrate:

You may have noticed that the variables defined by let and const do not have any values ​​associated with them, but the variables defined by var are set to undefined.

This is because during the creation phase, the engine checks the code to find variables and function declarations, and although the function declarations are completely stored in the environment, the variables are initially set to undefined (in the case of var), or are not initialized (in the case of let and const).

This is why you can access the variables defined by var (although undefined) before the declaration, but accessing the variables of let and const before the declaration will get a reference error.

This is what we call variable declaration promotion.

Execution phase

At this stage, all of these variables are completed and the code is finally executed.

Warning

During the execution phase, if the JavaScript engine cannot find the value of the let variable in the actual location declared in the source code, it will be assigned as undefined.