JS Engine Execution Process (i) __js

Source: Internet
Author: User
Tags closure

Overview

JS is a very flexible language, understanding the implementation of the JS engine is very important for us to learn JavaScript, but the internet to explain the JS engine of the article is mostly a little or only local analysis, such as only the analysis of event loop or variable elevation and so on, There is no comprehensive and in-depth analysis of the process. So I always want to do the detailed process of JS execution into a more detailed knowledge system, to help us understand and the overall understanding of JS.

Before we analyze this, we'll look at the following basic concepts:

JavaScript is a single-threaded language

In a browser, a page always has only one thread executing the JS script code (without actively opening a new thread).

JavaScript is a single-threaded language, but the code parsing is very fast and no parsing blocking occurs.

JavaScript is performed asynchronously, implemented through the event loop.

Let's start with a simpler code (no event loop) to verify that our understanding of the JS engine execution process is correct, as follows:

<script>
Console.log (Fun)

Console.log (person)
</script>

<script>
Console.log (person)

Console.log (Fun)

var person = "Eric";

Console.log (person)

function Fun () {
Console.log (person)
var person = "Tom";
Console.log (person)
}

Fun ()

Console.log (person)
</script>

We can analyze the above code, according to their own understanding of what the order of the output, and then executed in the browser, the result is the same, then on behalf of you have the JS engine to perform the process has a correct understanding, if not, there are still vague or unclear concepts and other issues. As a result, we do not discuss here, we use the above simple example of a comprehensive analysis of the JS engine implementation process, I believe that in understanding the process we will not be difficult to draw results, JS engine implementation process is divided into three stages:

Grammar analysis

Pre-compile phase

Implementation phase

Note: The browser first load by the <script> tab segmentation of JS code block, loaded JS code block finished, immediately entered the above three stages, and then in order to find the next code block, and then continue to perform the above three stages, Whether an external script file (not asynchronously loaded) or an internal script block of code is the same principle and is all in the same global scope. Grammar Analysis

When the JS script code block is loaded, it first enters the parsing phase. The main functions of this phase are:

Analyze the syntax of the JS script code block is correct, if it appears incorrectly, throw out a syntax error (SYNTAXERROR), stop the JS code block execution, and then continue to find and load the next block of code, if the syntax is correct, enter the precompilation phase

Syntax error the following figure:
pre-compile phase

JS code block through the parsing phase, the syntax is correct to enter the pre-compilation stage. Before the analysis of the precompiled phase, we first understand the operating environment JS, the operating environment is mainly three kinds:

Global Environment (JS code after loading, into the code to precompile into the global environment)

function environment (when a function call executes, it enters the function environment, and different functions have different functions)

Eval (not recommended, there will be security, performance issues)

Each into a different running environment will create a corresponding execution context (Execution), then in a section of JS program will generally create multiple execution contexts, JS engine will be the way the stack of these execution context processing, form the function call stack (called stack) , the bottom of the stack is always the global execution context, and the top of the stack is always the current execution context (Execution). function Call Stack

Function call stack is the use of stack access to manage the operating environment, characterized by advanced, backward first out.

We analyze the next section of the simple JS script code to understand the function call stack:

function Bar () {
var b_context = "Bar EC";

function foo () {
var f_context = "Foo EC";
}

Foo ()
}

Bar ()

The above code block, after parsing, goes into the precompilation phase, as shown in the following figure:

First into the global environment, create a global execution context, and push it into the stack stack Execution

Call bar function, enter bar function run environment, create bar function execution context (bar Execution contexts), push into stack stack

Call the Foo function inside the bar function, then go into the Foo function run environment, create the Foo function execution context (foo Execution contexts), and push it into the stack stack

At this point, the bottom of the stack is the global execution context (the global Execution context), and the top of the stack is the Foo function execution (foo Execution contexts), which, as shown above, starts out of the stack because no other functions are called within the Foo function.

After the Foo function completes, the stack top Foo function execution context (foo Execution contexts) First stacks

Bar function Execution (bar Execution context) stack

The Global Execution context is out of the stack when the browser or the tab closes.

Note: The execution of different running environments will go into the code precompilation and execution phases, and the parsing will create the execution context when the code block is loaded with the unified validation syntax

The execution context is understood to be the current execution environment, as opposed to the running environment. In the process of creating an execution context, the following three events were mainly done, as shown in the figure:

Creating variable objects (Variable object)

Establish scope chain (scope Chain)

To determine the point to create the variable object

Creating variable objects is mainly through the following procedures, as shown in the figure:

Creates a arguments object, examines the parameters in the current context, establishes the property and property values of the object, and only does so in the function environment (not the arrow function), which is not present in the global environment

Checks the function declarations of the current context, looking in code order, the function found is declared in advance, if the variable object of the current context does not have the function Name property, the variable object establishes a property with the function name, the property value is a reference to the memory address of the heap that contains the function, and if it does, it is overwritten by the new reference.

Check the variable declaration for the current context, find it in code order, declare the variable in advance, and if the variable object in the current context does not have the variable name property, establish a property with the variable name in the Variable object, a property value of undefined, or ignore the variable declaration if it exists

Note: In the Global environment, the window object is the variable object of the global execution context, and all variables and functions are property methods of the Window object.

So the function declaration advance and the variable declaration promotion are done in the Create variable object, and the function declaration priority is higher than the variable declaration.

We analyze a simple piece of code that helps us understand the process as follows:

function Fun (A, b) {
var num = 1;

function Test () {

Console.log (num)

}
}

Fun (2, 3)

Here we call the fun function in the global environment, creating the fun execution context, for the sake of understanding, for the time being, not to explain the scope chain and this point, as follows:

Funec = {
Variable Object
VO: {
Arguments objects
Arguments: {
A:undefined,
B:undefined,
Length:2
},

Test function


Num variable
num:undefined
},

Scope chain
Scopechain:[],

This points to
This:window
}

Funec represents the execution context of the fun function (fun Execution contexts is abbreviated to FUNEC)

The arguments attribute in the Fune variable object, which is written for ease of understanding, but is shown in the browser as an array of classes

<test reference> represents the reference of the test function in the heap memory address

Note: The Create variable object occurs in the precompiled phase, but is not yet in the execution phase, because the variable object is not accessible because the variable property in the Variable object is not yet assigned, the value is still undefined, and only if the variable property in the Variable object is assigned to the execution phase, A Variable object (Variable object) is converted to an active object (active object) for access, a process that is the vo–> AO process. Building a scope chain

The scope chain consists of a series of active objects in the upper environment, which is a variable object of the current execution environment (before the execution phase), which guarantees the orderly access of the current execution environment to variables and functions that meet the access permissions.

Clearing the scope chain can help us understand JS many problems, including closures, and so on, we combine a simple example to understand the scope chain, as follows:

var num = 30;

function Test () {
var a = 10;

function Innertest () {
var B = 20;

Return a + b
}

Innertest ()
}

Test ()

In the example above, when executed to call the Innertest function, enter the Innertest function environment. The global execution context and the test function execution context have entered the execution phase, and the Innertest function execution context creates variable objects in the precompiled phase, so their active objects and variable objects are AO (global), AO (test), and Vo (Innertest), respectively. The scope chain of the innertest is composed of a series of active objects in the upper environment, which is the variable object of the current execution environment (before the execution phase), as follows:

Innertestec = {

Variable Object


Scope chain
Scopechain: [VO (Innertest), AO (test), AO (global)],

This points to
This:window
}

We use arrays directly to represent the scope chain, and the active object or variable object of the scope chain can be directly understood as a scope.

The first item in the scope chain is always the current scope (the variable object or active object of the current context);

The last item is always the global scope (the active object of the global execution context);

The scope chain guarantees the orderly access of variables and functions, finding a variable or function along the scope chain from left to right, finding it stops looking, finding the global scope, and not finding it, and then throws a reference error.

Here we take a moment to think about what a closure is.

Let's take a look at the following simple example, as follows:

function foo () {
var num = 20;

function Bar () {
var result = num + 20;

return result
}

Bar ()
}

Foo ()

Because of a lot of different understanding of closures, including some of the books I read (such as JS Advanced program design), I am here directly to the browser parsing, the browser to understand the closure of the closure, the following figure:

As shown in the image above, the Chrome browser understands that the closure is Foo, and how the closure is defined by the browser's standard, I sum it to three points:

To define a new function inside a function

The new function accesses the local variable of the outer function, that is, the active object property that accesses the outer function environment

The new function executes, creates a new function execution context, and the outer function, which is the closure, determines this point

In the global context, the This property of the variable object in the global execution context points to window; The this point in the function environment is more flexible, it needs to be determined according to the execution environment and execution method, and a large number of typical examples need to be summarized. Summary

Because of the excessive content involved, the third phase (the implementation phase) is separated separately. Another new article for detailed analysis, the next article mainly describes the implementation phase of JS synchronization task execution and asynchronous task execution mechanism (event loop). If this article is wrong, please correct me.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.