why

To be a competent front-end developer, you must know the internal execution mechanism of Javascript. Execution context and execution stack is one of the key concepts in Javascript, but also one of the difficult ones. Understanding the execution context and execution stack also helps to understand the concepts of promotion mechanisms, scopes, closures, and so on in JS.

What is the

Execution context

1. What is

An execution context is an abstraction of the context in which the current Javascript code is being parsed and executed, and any code running in JS is in the execution context

Type 2.

There are three types of execution contexts

  • Global execution context:

Default, most basic execution context. Code that is not in any function is in the global execution context.

Two things are done: 1. Create a global object, which in the browser is the Window object. 2. Point this to the global object.

Only one global execution context can exist in a program.

  • Function execution context:

Each time a function is called, a new execution context is created for that function. Each function has its own execution context, but is created only when the function is called.

There can be many function execution contexts in a program. Each time a new execution context is created, it performs a series of steps in a specific order, as discussed later

  • The Eval function execution context:

The code running in the eval function also gets its own execution context, which is used infrequently and not discussed again

3. Lifecycle of execution context

The life cycle of an execution context consists of three stages: create stage → execute stage → reclaim stage

  • 1. Creation phase

When a function is called, but before any internal code is executed, it does three things:

Create a variable object: first initialize the function arguments and promote the function declaration and variable declaration.

Create scope chain: The scope chain is created after the variable object. The scope chain itself contains variable objects that are used to parse variables. When asked to resolve a variable, the search starts at the innermost level, and if not, goes to the parent scope of the next level until the variable is found.

Make sure this points to

Before a JAVASCRIPT script is executed, the code is parsed (this is why interpreted scripting languages are used in JS), creating an execution context in which variables and function declarations are extracted from the code. The variable is temporarily assigned to undefined, and the function is declared. This step is done, and then the formal execution of the program begins. (Variable promotion)

In addition, before a function is executed, a function execution context is created, just like the global context, except that the function execution context has additional arguments for this, arguments, and the function

  • 2. Implementation phase

Perform variable assignment and code execution

  • 3. Recycling phase

The execution context is removed from the stack and waits for the VM to reclaim the execution context

Variable promotion and this point to details

1. Variable declaration enhancement

Most programming languages declare variables first and then use them, but in JS things are a little different:

console.log(a); // undefined
var a = 10;
Copy the code

Refer Error: A is not defined, this is because of the claim of ascending (as defined), equivalent to the following code:

var a; // Declare that the default value is undefined "preparation" console.log(a); a = 10; / / assignmentCopy the code

2. Function declaration enhancement

Function foo(){} var foo = function(){} var foo = function(){}

console.log(f1); // function f1(){} function f1(){} console.log(f2); // undefined var f2 = function() {}; // Function expressionCopy the code

Function expression is equivalent to variable promotion, so undefined

Note: In cases where both functions and variables have the same name and are promoted, the function declaration takes precedence, so the variable declaration is overridden by the function declaration, but can be reassigned.

alert(a); Function a(){alert(' I am a function ')} function a(){alert(' I am a function '); } var a = "I am a variable "; alert(a); // Output: 'I am a variable'Copy the code

Let’s do a more complicated example

Function test (arg) {// Arg is "hi" console.log(arg); Function var arg = "hello"; function var arg = "hello"; function arg() { console.log("hello world") } console.log(arg); // Print hello}Copy the code

3. Make sure this points to

It is important to understand that the value of this is checked at execution time, not at definition. Why? Because this is part of the execution context, and the execution context needs to be determined before the code is executed, not when it is defined.

Function foo() {console.log(this.a) //1} var a = 1 foo() {console.log(this); } var obj={fn:fn}; obj.fn(); Function CreateJsPerson(name,age){function CreateJsPerson(name,age){ //=>p1.name=name this.age=age; //=>p1.age=age} var p1=new CreateJsPerson(" 下 载 ",48); Function add(c, d){return this.a + this.b + c + d; } var o = {a:1, b:3}; add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 add.apply(o, [10, 20]); <button id="btn1"> This </button> <script type="text/javascript"> let btn1 = document.getElementById('btn1'); let obj = { name: 'kobe', age: 39, getName: function () { btn1.onclick = () => { console.log(this); //obj }; }}; obj.getName(); </script>Copy the code

Let’s explain each of these cases one by one

  • For calling foo directly, no matter where foo is placed, this must be window, right
  • For obj.foo(), we just need to remember that whoever called the function is this, so this in the foo function is the obj object in this scenario
  • In the constructor pattern, the occurrence of this. XXX = XXX in the class (in the function body) is an instance of the current class
  • Call, apply, and bind: this is the first argument
  • The arrow function this points to: the arrow function does not have its own this. If it does, this of the outer function is the this of the inner arrow function. If not, this is the window.

Execute the context stack

The JavaScript engine creates an execution context stack to manage the execution context. The execution context stack can be thought of as a stack structure for storing function calls, following the principle of first in, last out.

From the above flow chart, we need to remember a few key points:

  • JavaScript executes on a single thread and all code is queued.

  • When the browser executes global code, it first creates the global execution context, pushing it to the top of the execution stack.

  • Each time a function is executed, the execution context of the function is created and pushed to the top of the stack. After the execution of the current function completes, the execution context of the current function goes off the stack and waits for garbage collection.

  • The browser’s JS execution engine always accesses the execution context at the top of the stack.

  • There is only one global context, which is pushed out when the browser closes.

    var color = “blue”; function changeColor() {

    var anotherColor = “red”;

    function swapColors() {

    var tempColor = anotherColor;

    anotherColor = color;

    color = tempColor;

    }

    swapColors(); } changeColor();

The above code runs as follows:

  • When the code is loaded in the browser, the JavaScript engine creates a global execution context and pushes it onto the current execution stack
  • When a changeColor function is called, the js execution engine immediately creates a changeColor execution context (EC for short) and pushes this execution context into the execution stack (ECStack for short).
  • The swapColors function is called during the execution of changeColor. Similarly, an execution context for swapColors is created and pushed onto the execution stack before the execution of the swapColors function.
  • When the swapColors function completes, the execution context of the swapColors function is removed from the stack and destroyed.
  • When the changeColor function completes, the execution context of the changeColor function is removed from the stack and destroyed.