Execution order

If you want to ask about the order of JavaScript code execution, most developers who have written JavaScript will have an intuitive impression, that is, sequential execution, first look at a piece of code:

var foo = function () {

    console.log('foo1');

}

foo();  // foo1

var foo = function () {

    console.log('foo2');

}

foo(); // foo2
Copy the code

Then look at this code:

function foo() {

    console.log('foo1');

}

foo();  // foo2

function foo() {

    console.log('foo2');

}

foo(); // foo2
Copy the code

The result is two foo2.

This is because the JavaScript engine does not analyze and execute the program line by line, but 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.

Question:

What exactly is the division of “paragraph” in “paragraph by paragraph”?

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

Executable code

What types of JavaScript executable code can include?

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

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

To simulate the behavior of an execution context stack, we define the execution context stack as an array:

ECStack = [];
Copy the code

When JavaScript begins 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 cleared, so there is always a globalContext at the bottom of the ECStack before the program ends:

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:

// pseudocode // 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

Consider:

var block = "global scope";
function checkscope(){
    var block = "local scope";
    function f(){
        return block;
    }
    return f();
}
checkscope();
Copy the code
var block = "global scope";
function checkscope(){
    var block = "local scope";
    function f(){
        return block;
    }
    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

In order to explain the difference in the execution of the two functions in more detail, we need to explore what is involved in the execution context, so please read the next article on JavaScript in Depth variable Objects.