JavaScript delves into article 3 of this series, explaining how context stacks are executed, and answering some of the harder thinking questions in Article 2.

Sequential execution?

If asked about the order of JavaScript code execution, most JavaScript developers will have an intuitive impression that it is sequential execution, after all:

var foo = function () {

    console.log('foo1');

}

foo();  // foo1

var foo = function () {

    console.log('foo2');

}

foo(); // foo2Copy the code

However, look at this code:


function foo() {

    console.log('foo1');

}

foo();  // foo2

function foo() {

    console.log('foo2');

}

foo(); // foo2Copy the code

The result is two foo2.

As anyone who has skimped through the interview questions knows, this is because the JavaScript engine doesn’t analyze and execute the program line by line, it analyzes execution paragraph by paragraph. When executing a piece of code, there is a “prep work”, such as variable promotion in the first example and function promotion in the second example.

But what this article really wants us to think about is: how is the “paragraph” in “paragraph by paragraph” actually divided?

What kind of code does a JavaScript engine “prepare” for?

Executable code

Which brings us to what types of JavaScript executable code are there?

There are three types of global code, function code, and eval code.

For example, when a function is executed, preparation takes place, which is, let’s use a more technical term, “Execution Context”.

Execution context stack

The question then arises, how do we manage the creation of so many execution contexts when we write so many functions?

So the JavaScript engine creates an Execution Context stack (ECS) to manage the Execution context

To simulate the execution context stack behavior, let’s define the execution context stack as an array:

    ECStack = [];Copy the code

When JavaScript starts to interpret execution code, the first thing it encounters is global code, so initialization pushes a global execution context onto the execution context stack, which we call a globalContext, and only when the entire application ends, The ECStack is emptied, so there is always a globalContext at the bottom of the ECStack:

    ECStack = [
        globalContext
    ];Copy the code

JavaScript now encounters the following code:

function fun3() {
    console.log('fun3')}function fun2() {
    fun3();
}

function fun1() {
    fun2();
}

fun1();Copy the code

When a function is executed, an execution context is created and pushed onto the execution context stack. When the function is finished, the execution context of the function is ejected from the stack. With that in mind, let’s see what we can do with the code above:

/ / pseudo code

// fun1()ECStack.push(<fun1> functionContext); Ecstack.push (<fun2> functionContext); // fun2 also calls fun3! ECStack.push(<fun3> functionContext); Ecstack.pop (); Ecstack.pop (); Ecstack.pop (); // Javascript then executes the following code, but there is always a globalContext at the bottom of the ECStackCopy the code

Answer the thought questions

Ok, now that we know how the execution context stack handles execution context, let’s look at the final question from the previous article “JavaScript Deep Lexical and dynamic scopes” :

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();Copy the code
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();Copy the code

Two pieces of code execute the same, but what are the differences between them?

The answer is that the execution context stack changes differently.

Let’s simulate the first code:

ECStack.push(<checkscope> functionContext);
ECStack.push(<f> functionContext);
ECStack.pop();
ECStack.pop();Copy the code

Let’s simulate the second code:

ECStack.push(<checkscope> functionContext);
ECStack.pop();
ECStack.push(<f> functionContext);
ECStack.pop();Copy the code

Is it different?

Answer, of course, summed up the execution context stack change is different, still have a feeling of wanting more, in order to explain in more detail the difference on the two functions, we need to explore the execution context contains what content, so welcome to the next “JavaScript into the variable object”.

Next article

JavaScript Into Variable Objects

In-depth series

JavaScript In-depth series directory address: github.com/mqyqingfeng… .

This in-depth JavaScript series is designed to help you understand the basics of JavaScript, including prototypes, scopes, execution contexts, variable objects, this, closures, passing by value, call, apply, bind, new, and inheritance.

If there is any mistake or not precise place, please be sure to give correction, thank you very much. If you like or are inspired by it, welcome star and encourage the author.