Javascript Engine working mechanism detailed _javascript tips

Source: Internet
Author: User
Tags define function define local

Javascript Engine working mechanism

JavaScript from definition to execution, JS engine in the implementation layer do a lot of initialization work, so before learning the JS engine working mechanism, we need to introduce a number of related concepts: Execution environment stack, global object, execution Environment, variable object, active object, scope and scope chain, etc. These concepts are the core components of JS engine work. The purpose of this article is not to explain each concept in isolation, but to analyze it through a simple demo, explaining the details of the JS engine from definition to execution, and the role of these concepts in it.


var x = 1; Define a global variable x
function A (y) {
  var x = 2;//define a local variable x
  function B (z) {//define an internal function B
    Console.log (x+y+z);
  }
  return B;//returns reference
to function b var C = A (1); Execute A, return B
C (1);//execute function B

This demo is a closure, the execution result is 4, we will be global initialization, execute function A, execute function b Three stages to analyze the working mechanism of JS Engine:

First, global initialization

The JS engine needs to complete the following three initialization tasks as it enters a piece of executable code:

First, create a global object that has only one global object, its properties accessible anywhere, and its presence along with the entire lifecycle of the application. When a global object is created, it uses the common JS objects such as math,string,date,document as its properties. Since this global object cannot be accessed directly by name, there is another property window and points to itself so that the global object can be accessed through the window. The general structure of the global object is simulated with pseudo code as follows:

Create a Global object
var globalobject = { 
  math:{},
  string:{},
  date:{},
  document:{},//dom operation
  ...
  Window:this//Let the window attribute point to itself
}

Then, the JS engine needs to build an execution environment stack (Execution context stack), at the same time, create a global execution Environment (Execution context) EC, and push this global execution environment EC into the execution environment stack. The role of the execution environment stack is to ensure that the program is executed in the correct order. In JavaScript, each function has its own execution environment, and when a function is executed, the execution environment of the function is pushed to the top of the execution environment stack and gets execution power. When this function completes, its execution environment is removed from the top of the stack, and the execution power is returned to the execution environment before it is executed. We use pseudo code to simulate the relationship between the execution environment stack and the EC:

var ecstack = []; Defines an execution environment stack, similar to an array of

var EC = {};  To create an execution space, the
//ecma-262 specification does not explicitly define the EC's data structure, which you can understand as a space allocated in memory

Ecstack.push (EC);/Enter function, press into execution environment
Ecstack.pop (EC); After the function returns, deletes the execution environment

Finally, the JS engine also creates a global variable object (Varibale object) VO that is associated with the EC. And pointing Vo to the Global object, VO contains not only the original attributes of the global object, but also the globally defined variable x and function A, while the function A is defined as a An internal property scope was added and the scope was pointed to VO. Each function, when defined, creates a scope attribute associated with it, and scope always points to the environment in which the function is defined. The ecstack structure at this point is as follows:

Ecstack = [//  Executive Environment Stack
  EC (g) = {//  Global Execution Environment
    VO (g): {///define global Variable Object
      ...//include global object original attribute
      x = 1;//define variable x
      A = function () {...}; Define function A
      a[[scope]] = this;//define scope of a, and assign value to VO itself
    }
];

II. Executive Function A

When executing into a (1), the JS engine needs to complete the following tasks:

First, the JS engine creates the execution environment EC for function A, and then the EC pushes the top of the execution environment stack and gets execution power. At this time the execution environment stack has two execution environments, namely the global execution environment and function a execution environment, A's execution environment at the stack top, the global execution environment at the bottom of the stack. Then, create the scope chain (scope Chain) of function A, in JavaScript, each execution environment has its own scope chain, for identifier resolution, and when the execution environment is created, its scope chain is initialized to the object contained in the scope of the currently running function.

Next, the JS engine creates an active object (Activation object) AO for the current function, where the active object plays the role of the variable object, but it is called differently in the function (you can assume that the variable object is a general concept and the active object is a branch of it), AO contains the parameters of the function, the arguments object, the This object, and the definitions of local and internal functions, and AO is pushed to the top of the scope chain. It should be noted that when defining function B, the JS engine also adds a scope attribute to B and points the scope to the environment in which the function B is defined, and the environment in which the function B is defined is the active object AO of a, and AO is at the front of the list, and because the linked list has the characteristics of end-to-end, So the scope of function B points to the entire scope chain of a. Let's take a look at this ecstack structure:



Ecstack = [  //Executive Environment Stack
  EC (a) = {  //a execution Environment
    [Scope]:vo (G),//VO is global variable object
    AO (a): {//Create Activity object for function A
      y:1,< C7/>x:2,//define local variable x
      b:function () {...},//define function B
      B[[scope]] = this;//this refers to the AO itself, while AO is at the top of the Scopechain, so B[[scope ] pointing to the entire scope chain
      arguments:[],//The arguments that we normally access in the function is the arguments
      This:window//function in AO. Point to Caller Window object
    }, the
    Scopechain:<ao (a),a[[scope]]>//list is initialized to A[[scope] and then AO is added to the top of the scope chain, at this point in the scope chain of a: AO (a)->vo (G)
  },
  EC (g) = {//  Global Execution Environment
    VO (g): {////Create global variable Object
      ...//include global object original attribute
      x = 1;//define variable x
      A = function () {...}; Define function A
      a[[scope]] = this;//define a scope,a[[scope] = = VO (G)
    }
  }
];

Third, executive function b

After function A is executed, the reference to B is returned and assigned to the variable C, and execution C (1) is equivalent to executing B (1), and the JS engine needs to do the following:

First, as above, create the execution Environment EC for function B, and then the EC pushes the top of the execution environment stack and gets execution power. At this time the execution environment stack has two execution environment, is the global execution environment and function B execution Environment, b execution Environment at the top of the stack, the global execution environment at the bottom of the stack. (Note: When function A returns, the execution environment of a is removed from the stack, leaving only the global execution environment), then the scope chain of function B is created and initialized to the object contained in scope of function B, which contains the scope chain of a. Finally, the active object ao of function B is created, and the parameter Z of B, the arguments object and the This object as AO properties. At this point Ecstack will become this:

Ecstack = [  //Executive Environment stack
  EC (b) = {  //Create execution Environment for B and at the top of the scope chain
    [Scope]:ao (a),//point to function A's scope chain, AO (a)->vo (G)
    var AO (b) = {///Create Activity object for function B
      z:1,
      arguments:[],
      this:window
    }
    Scopechain:<ao (b), b[[ Scope]]>//list is initialized to B[[scope]], then AO (b) is added to the list header, at this time the scope chain of B: AO (b)->ao (a)-vo (G)
  },
  EC (a),//a execution Environment has been removed from the top of the stack ,
  EC (G) = {//  Global Execution Environment
    vo:{//define global Variable Object
      ...//contains the global object's original property
      x = 1;//define variable x
      A = function () {...}; Define function A
      a[[scope]] = this;//define a scope,a[[scope] = = VO (G)
    }
  }
];

When function B executes "x+y+z", you need to have an X, Y, z three identifiers for one by one parsing, the parsing process follows the variable lookup rule: First find out if the property exists in its own active object and, if it exists, stop the lookup and return, and if it does not exist, continue to search the top of its scope chain until it is found , returns "Undefined" if the variable is not found on the entire scope chain. From the above analysis, we can see that the scope chain of function B is this:

AO (B)->ao (A)->vo (G)

Therefore, the variable x is found in AO (a) without looking for x in Vo (G), and the variable y is found in AO (a), and the variable z is found in its own AO (B). So the execution result: 2+1+1=4.

Simple summary of the language

Understand the JS engine's working mechanism, we can not only stay in understanding the concept of the level, but to use it as a basic tool to optimize and improve our actual work in the code, improve the efficiency of implementation, the actual value is our real goal. Just take the variable lookup mechanism, if your code is nested deep, every time a global variable is referenced, the JS engine will look for the entire scope chain, such as the bottom window and document object in the scope chain, so we can do a lot of performance tuning around this problem, Of course, there are other aspects of optimization, no longer to repeat here, this article just as a trigger!

Thank you for reading, I hope to help you, thank you for your support for this site!

Related Article

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.