• Understanding Execution Context and Execution Stack in Javascript
  • Sukhjinder Arora
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: CoolRice
  • Proofreader: Linxuesia, CoderMing

Photo by Greg Rakozy, author of Unsplash

If you are or want to be a JavaScript developer, you must know how JavaScript programs are executed internally. Understanding the execution context and execution stack is critical to understanding other JavaScript concepts such as variable declaration promotion, scope, and closures.

Understanding the concepts of execution context and execution stack will make you a better JavaScript developer.

Without further ado, let’s get started 🙂


To share theBitBlog ❤ ️

Using the components provided by the Bit application as building blocks, you are the architect. Share, discover, and develop components with your team anytime, anywhere.

  • Bit – Share and create code componentsBit helps you share, discover, and use code components across projects and applications to create new features and…

What is an execution context?

In short, an execution context is an abstraction of the context in which JavaScript code is evaluated and executed. Whenever Javascript code is running, it is running in an execution context.

The type of execution context

There are three types of execution context in JavaScript.

  • Global execution context— This is the default or base context, and any code that is not inside a function is in the global context. It does two things: create a global Window object (in the case of the browser) and set itthisIs equal to the global object. There is only one global execution context in a program.
  • Function execution Context – Each time a function is called, a new context is created for that function. Each function has its own execution context, but is created when the function is called. There can be any number of function contexts. Each time a new execution context is created, it performs a series of steps in a defined order (discussed later).
  • The Eval function executes the context– perform inevalThe code inside a function also has its own execution context, which JavaScript developers don’t often useevalSo I won’t talk about it here.

Execution stack

An execution stack, or “call stack” in other programming languages, is a stack with LIFO (LIFO) data structures that are used to store all execution contexts created while the code is running.

When the JavaScript engine first encounters your script, it creates a global execution context and pushes it onto the current execution stack. Every time the engine encounters a function call, it creates a new execution context for that function and pushes it to the top of the stack.

The engine executes functions whose execution context is at the top of the stack. When the function completes execution, the execution context pops out of the stack and the control flow moves to the next context in the current stack.

Let’s take a look at the following code example:

let a = 'Hello World! ';

function first() {
  console.log('Inside first function');
  second();
  console.log('Again inside first function');
}

function second() {
  console.log('Inside second function');
}

first();
console.log('Inside Global Execution Context');
Copy the code

The execution context stack of the above code.

When the above code loads in the browser, the JavaScript engine creates a global execution context and pushes it onto the current execution stack. When the first() function call is encountered, the JavaScript engine creates a new execution context for the function and pushes it to the top of the current execution stack.

When second() is called from within the first() function, the JavaScript engine creates a new execution context for the second() function and pushes it to the top of the current execution stack. When second() completes, its execution context is popped off the current stack and the control flow moves to the next execution context, that of the first() function.

When first() completes, its execution context pops off the stack and the control flow reaches the global execution context. Once all code has been executed, the JavaScript engine removes the global execution context from the current stack.

How do I create an execution context?

Now that we’ve looked at how JavaScript manages execution contexts, let’s look at how the JavaScript engine creates execution contexts.

There are two phases to creating an execution context: 1) the creation phase and 2) the execution phase.

The Creation Phase

Before the JavaScript code executes, the execution context goes through the creation phase. Three things happen during the creation phase:

  1. The determination of the this value, known as the This binding.
  2. Create the lexical environment component.
  3. Create the variable environment component.

So the execution context is conceptually expressed as follows:

ExecutionContext = { ThisBinding = <this value>, LexicalEnvironment = { ... }, VariableEnvironment = { ... }},Copy the code

This binding:

In the context of global execution, the value of this points to a global object. In browsers, this refers to the Window object.

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

let foo = {
  baz: function() {
  console.log(this);
  }
}

foo.baz();   // 'this'reference'foo'Because the'baz'/ / object'foo'calllet bar = foo.baz;

bar();       // 'this'Points to the global Window object because // does not specify a reference objectCopy the code

Lexical environment

The official ES6 documentation defines the lexical environment as

A lexical environment is a canonical type that defines the associations 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, a lexical environment is a structure that holds identity-variable mappings. (The identifier here refers to the name of the variable/function, and the variable is a reference to the actual object [containing the object of the function type] or the original data).

Now, inside the lexical environment there are two components :(1) the environment logger and (2) a reference to the external environment.

  1. The environment logger is the actual location where variable and function declarations are stored.
  2. A reference to an external environment means that it has access to its parent lexical environment (scope).

There are two types of lexical environments:

  • The global environment(in the context of global execution) is a lexical environment that has no references to the external environment. The external environment reference for the global environment isnull. It has built-in Object/Array/ etc., prototype functions in the environment logger (associated with global objects such as window objects) and any user-defined global variables, andthisThe value points to the global object.
  • In a function environment, user-defined variables within a 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.

Environment loggers also come in two types (as above!) :

  1. Declarative environment loggers store variables, functions, and parameters.
  2. The object environment logger is used to define the relationship between variables and functions that appear in the global context.

In short,

  • In a global environment, the environment logger is the object environment logger.
  • In a functional environment, the environment logger is the declarative environment logger.

Note – For function environments, the declarative environment logger also contains a arguments object passed to the function (which stores the index and parameter mapping) and the length of the argument passed to the function.

Abstractly, the lexical environment in pseudocode looks like this:

GlobalExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object"} outer: <null>}} FunctionExectionContext = {LexicalEnvironment: {EnvironmentRecord: {Type:"Declarative"} outer: <Global or outerfunction environment reference>
  }
}
Copy the code

Variable environment:

It is also a lexical environment whose environment logger holds bindings created in the execution context of variable declaration statements.

As mentioned above, the variable environment is also a lexical environment, so it has all the attributes of the lexical environment defined above.

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

Let’s look at sample code to understand the above concepts:

let a = 20;
const b = 30;
var c;

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

c = multiply(20, 30);
Copy the code

The execution context looks like this:

GlobalExectionContext = {

  ThisBinding: <Global Object>,

  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object"A: < uninitialized >, b: < uninitialized >, multiply: < func >} outer: <null>}, VariableEnvironment: { EnvironmentRecord: { Type:"Object"} outer: <null>}} FunctionExectionContext = {ThisBinding: <Global Object>, LexicalEnvironment: { EnvironmentRecord: { Type:"Declarative"}, outer: <GlobalLexicalEnvironment>}, VariableEnvironment: { EnvironmentRecord: { Type:"Declarative"Outer: <GlobalLexicalEnvironment>}}Copy the code

Note – The function execution context is created only if the multiply function is called.

You may have noticed that the let and const variables are not associated with any value, but the var variable is set to undefined.

This is because during the creation phase, the engine examines the code for variable and function declarations, which are stored entirely in the environment but are initially set to undefined (in the case of var) or uninitialized (in the case of let and const).

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

This is what we call variable declaration enhancement.

Execution phase

This is the easiest part of the whole article. At this stage, all of these variables are allocated and the code is executed.

Note – at execution time, if the JavaScript engine cannot find the value of the let variable at the actual location declared in the source code, it will be assigned the value of undefined.

conclusion

We’ve already discussed how JavaScript programs are executed internally. While you don’t need to know all of these concepts to be a great JavaScript developer, a good understanding of these concepts will help you understand other concepts, such as variable declaration enhancement, scope, and closures more easily and in depth.

That’s it, if you find this article useful, click the 👏 button and feel free to comment below! I would be happy to discuss 😃 with you.


To share theBitThe blog

Bit makes it easy to share small components and modules across projects and applications, enabling you and your team to build code faster. Share, discover, and develop components with your team anywhere, anytime.

  • Bit – Share and create code componentsBit helps you share, discover, and use code components across projects and applications to create new features and…

To learn more

  • 11 React UI Component Libraries you should Know about in 201811 React component libraries with great components for building the next generation of application UI interfaces.

  • 5 Tools to Speed up vue.js application development: Speed up your vue.js application development.

  • How to write better code in React: 9 practical tips for writing better code in React: Learn Linting, propTypes, PureComponent and more.

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.