The Lexical scope of JavaScript)

Source: Internet
Author: User
Document directory
  • Key points of the syntax analysis tree

You should have written a similar code. In fact, what I want to express here is that sometimes a method definition is 108,000 different from that used. When the method is executed, what variables can be accessed and what variables cannot be accessed? How can this problem be determined? This is the problem we need to analyze this time --Lexical Scope

var classA = function(){    this.prop1 = 1;}classA.prototype.func1 = function(){    var that = this,        var1 = 2;     function a(){        return function(){            alert(var1);            alert(this.prop1);        }.apply(that);    };    a();}var objA = new ClassA();objA.func1();

Lexical Scope: The scope of a variable is determined at definition rather than execution. That is to say, the lexical scope depends on the source code and can be determined through static analysis. Therefore, the lexical scope is also called static scope. Except with and Eval, we can only say that the JS scope mechanism is very close to the lexical scope ).

The following are a few small cases to learn more about lexical scopes andClosureIt is essential to have some underlying concepts and theoretical knowledge during Javascript execution.

Classic case column reproduction 1. Classic Case 1
/* Code in the global (window) Field */function a (I) {var I; alert (I) ;}; A (10 );

Q: What will the above Code output?
Answer: Yes, 10 is displayed. The specific execution process should be like this

Function A has an I parameter. When function a is called, input 10 arguments. The I parameter is 10.
Next, define a local variable I with the same name without assigning a value.
Alert output 10

Thinking: is the local variable I and the shape parameter I the same bucket?

2. Classic Case 2
/* Code in the global (window) Field */function a (I) {alert (I); alert (arguments [0]); // arguments [0] should be the form parameter I var I = 2; alert (I); alert (arguments [0]) ;}; A (10 );

Q: What will the above Code output? (, | ))
Answer: The running result in firebug is the second 10, 10, 2, 2, right... The following describes the specific execution process.

Function A has an I parameter. When function a is called, input 10 arguments. The I parameter is 10.
The first alert outputs the value of I 10.
The second alert outputs arguments [0], which should also be I
Then define a local variable I and assign it to 2. At this time, the local variable I = 2
The third Alert outputs the value 2 of the local variable I.
The fourth alert outputs arguments [0] again.

Thinking: Can the local variable I and the parameter I have the same value?

3. Typical Case 3
/* Code in the global (window) Field */function a (I) {var I = I; alert (I) ;}; A (10 );

Q: What will the above Code output? (Undefined | 10 ))
Answer: The running result in firebug is 10. The specific execution process is briefly described below.

The first clause declares a local variable with the same name as the form parameter I. According to the result, we know that the next I point
This is equivalent to assigning the value 10 of the parameter I to the local variable I.
The second alert will certainly output 10

Thinking: Combined with Case 2, here we can basically show that the local variable I and the form parameter I point to the same storage address!

4. Typical Case 4
/* Code segment in the global (window) Field */var I = 10; function a () {alert (I); var I = 2; alert (I );}; A ();

Q: What will the above Code output? (Boy, you're not dead this time! Wow Haha, I will not give you the option)
Answer: The running result in firebug is undefined, 2. The specific execution process is briefly described below.

The first alert outputs undefined
The second alert output 2

Think: What's the problem?

5. Typical Case 5 .............. N

When you see the above examples, you may think about how it is possible that I have written JavaScript for a few years, and I will hesitate to give such a simple example, and the result may be wrong. In fact, the possible reason is: we can quickly write a method, but in the end, how is the internal implementation of the method? What are the execution details? You may not have any in-depth study or understanding. To understand these details, we need to understand how the JS engine works. So we will give a slightly more in-depth introduction to the parsing process of a method by the JS engine.

Code parsing process 1. Javascript execution sequence

The compilation steps include lexical analysis, syntax analysis, semantic check, code optimization, and byte generation.
After obtaining the syntax analysis tree through lexical analysis and syntax analysis, the interpreted language can start to be executed. Here is a simple and original principle of the parsing process. It is only for reference. The detailed parsing process (different JS engines) also requires further research.

JavascriptExecution process. If a Document Stream contains multiple script code segments (JavaScript code separated by SCRIPT tags or imported JS files), the running sequence is as follows:

  1. Read the first code segment (the JS execution engine does not execute the program one by one, but analyzes and executes the program one by one)
  2. Perform lexical analysis and syntax analysis. If there is a mistake, a syntax error is reported (for example, parentheses do not match), and jump to Step 5.
  3. Perform "pre-resolution" on the [Var] variable and [function] definition (no error will be reported, because only the correct declaration is parsed)
  4. Run the code segment. If the code segment is incorrect, an error is returned (for example, the variable is not defined)
  5. If there is another code segment, read the next code segment and repeat Step 2.
  6. End
2. Special Instructions

All js code in the window field can be regarded as an "anonymous method" and will be automatically executed, other methods in this "anonymous method" are executed only when they are displayed and called.

3. Key Steps

The above process is divided into two phases.

Javascript Parsing: Constructs a legal syntax analysis tree through syntax analysis and pre-resolution.
JavaScript Execution: Execute a specific function. When the JS engine executes each function instance, it will create an execution environment (executioncontext) and activity object (activeobject) (they belong to the Host object, is consistent with the life cycle of the function instance)

3. Key Concepts

Here, we will emphasize the following concepts, which will be represented by one entity below for your understanding.

Syntax analysis tree(Syntaxtree): intuitively shows the information about this Code. The specific implementation is that the JS engine creates tables to record the variables in each method ), method set (functions) and scope (scope.

Execution Environment(Executioncontext): it can be understood as an object that records the "external description" of the currently executed method, and records the type, name, parameters, and activity object of the method to be executed (activeobject ).

Activity object(Activeobject): it can be understood as an object that records the current method [internal execution information], recording the internal variable set (variables), nested function set (functions), and real parameters (arguments) scopechain and other information required for execution. The internal variable set (variables) and nested function set (functions) are directly copied from the syntax analysis tree created in step 1.

Lexical Scope: The scope of a variable is determined at definition rather than execution. That is to say, the lexical scope depends on the source code and can be determined through static analysis. Therefore, the lexical scope is also called static scope. Except with and Eval, we can only say that the JS scope mechanism is very close to the lexical scope ).

Scope chain: The implementation mechanism of lexical scopes is scopechain ). The scope chain is a set of Name Lookup mechanisms. First, it is searched in the activeobject of the current execution environment. If it is not found, it is searched in the parent activeobject along the scope chain, always find the global object ).

4. entity representation JavaScript parsing Simulation

It is estimated that everyone is still confused here. What is the syntax analysis tree? What is the syntax analysis tree like? How is the scope chain implemented? What is the content of the activity object, still not very clear. Next we will simulate the entire parsing process through a piece of actual code. We will create the syntax analysis tree and activity objects to understand the scope, how is the scope chain implemented?

1. Simulate code
/* Code segment in the global (window) Field */var I = 1, j = 2, K = 3; function a (O, P, X, q) {var x = 4; alert (I); function B (R, S) {var I = 11, y = 5; alert (I); Function C (t) {var z = 6; alert (I) ;}; // function expression var d = function () {alert (y) ;}; C (60 ); D () ;}; B (40, 50) ;}a (10, 20, 30 );
2. syntax analysis tree

The above code is very simple, that is, some global variables and global methods are defined first, and then local variables and local methods are defined in the method. Now the JS interpreter reads this code and starts parsing, as mentioned above, the JS engine will first obtain the syntax analysis tree through syntax analysis and pre-resolution. As for what the syntax analysis tree looks like, there will be some information.

Below we use a simple structure: a JS object (to clearly express the reference relationship between various objects, Here we only represent pseudo objects and may not be able to run) to describe the syntax analysis tree (this is something we are familiar with. We should not go into the actual structure, but it must be much more complicated. Here we want to simplify the parsing process to help you understand it ).

/*** Simulate the creation of a syntax analysis tree and store the variables and methods in the function */var syntaxtree ={// the global object in the syntax analysis tree represents window: {variables: {I: {value: 1}, J: {value: 2}, K: {value: 3 }}, functions: {A: This. A }}, A: {variables: {X: 'undefined'}, functions: {B: This. b}, scope: This. window}, B: {variables: {y: 'undefined'}, functions: {C: This. c, D: This. d}, scope: This. a}, C: {variables: {z: 'undefined'}, functions :{}, scope: This. b}, D: {variables :{}, functions :{}, scope: {myname: D, scope: This. B }}};

The above is a simple representation of the syntax analysis tree. As we analyzed earlier, the syntax analysis tree mainly records the variables and functions in each function) and scope ).

Key points of the syntax analysis tree
  1. In a variables set, only variables are defined and there is no variable value. At this time, all the variable values are "undefined"
  2. Scope, according to the characteristics of the lexical scope, the scope of each variable is clearly defined at this time, and will not change with the execution environment. [What do you mean? That is, we often return a method back and execute it in another method. During execution, the scope of variables in the method follows the scope defined by the method. In fact, what I want to express here is that no matter how complicated and far you are, You can execute this method to determine whether the variables in the method can be accessed or you have to go back to the method definition for verification]
  3. Scope creation rules:
    A. For function declarations and anonymous function expressions, [Scope] is the scope of the function when it is created.
    B. for a function expression with a name, the top of [Scope] is a new JS object (that is, inheriting the object. prototype), this object has two attributes, the first is its own name, the second is the defined scope, the first function name is used to ensure that the code inside the function can access its own function name without error for recursion.
3. Execution Environment and activity objects

After the syntax analysis is complete, run the code. When we call every method, the JS engine automatically creates an execution environment and an activity object for it. They are consistent with the life cycle of the Method Instance, provide necessary execution support for method execution. For the above methods, we have set up activity objects for them in a unified way (the activity object is generated only when the method is executed, for ease of demonstration, the activity objects of all methods are defined here), as follows:
Execution Environment

/*** Execution environment: execution environment created during function execution */var executioncontext = {window: {type: 'global', name: 'global', body: activeobject. window}, A: {type: 'function', name: 'A', body: activeobject. a, scopechain: This. window. body}, B: {type: 'function', name: 'B', body: activeobject. b, scopechain: This. a. body}, C: {type: 'function', name: 'C', body: activeobject. c, scopechain: This. b. body}, D: {type: 'function', name: 'D', body: activeobject. d, scopechain: This. b. body }}

The execution environment of each method above stores information such as the corresponding method type (function), Method Name (funcname), activity object (activeobject), and scope chain (scopechain, the key points are as follows:

Body property, direct to the activity object of the current method
Scopechain attribute and scope chain. It is a linked list structure. According to the scope attribute corresponding to the current method in the syntax analysis tree, it points to the activity object (activceobject) of the method corresponding to the scope ), variable Search follows this chain.
Activity object

/*** Activity object: List of activity objects created during function execution */var activeobject = {window: {variables: {I: {value: 1}, J: {value: 2}, K: {value: 3 }}, functions: {A: This. A }}, A: {variables: {X: {value: 4 }}, functions: {B: syntaxtree. b}, parameters: {o: {value: 10}, P: {value: 20}, X: This. variables. x, Q: 'undefined'}, arguments: [this. parameters. o, this. parameters. p, this. parameters. x]}, B: {variables: {y: {value: 5 }}, functions: {C: syntaxtree. c, D: syntaxtree. d}, parameters: {R: {value: 40}, S: {value: 50 }}, arguments: [this. parameters. r, this. parameters. s]}, C: {variables: {z: {value: 6 }}, functions :{}, parameters: {u: {value: 70 }}, arguments: [This. parameters. u]}, D: {variables :{}, functions :{}, parameters :{}, arguments: []}

Each of the above activity objects stores the required information for executing the corresponding method, such as the internal variable set (variables), nested function set (functions), parameter (parameters), and real parameter (arguments, key Points of activity objects

Create an activity object, and copy the internal variable set (variables) and nested function set (functions) of the method from the syntax analysis tree)
Method, and all the internal variable sets in the activity object are reset to undefined.
Create a parameters object and an arguments object with the same name as a real parameter. The reference relationship is between the parameter and the variable.
Execute the value assignment statement in the method to assign values to the variables in the variable set.
The Variable Search Rule is first searched in the activeobject of the current execution environment. If it is not found, it is searched in the activeobject pointed to by the attribute scopechain in the execution environment until the global object (window)
After the method is executed, the internal variable value is not reset. For how to destroy the variable, see the following
The life cycle of the variable in the method depends on whether the Method Instance has active reference. If not, the active object is destroyed.
6 and 7 are the root causes for the closure to access external variables.

Reinterpreting classic cases

According to [in a method, a real parameter with the same name is referenced between the form parameter and the variable, that is, the processing of the JS engine is a variable with the same name and the form parameter both reference the same memory address ], therefore, the change of arguments in No. 2 will affect local variables.

Case 4

Based on the JS Engine Variable Search rules, search for them in the activeobject of the current execution environment. If not, search for them in the activeobject indicated by the scopechain attribute in the execution environment until the global object (window) because the definition of variable I is found in the current activeobject, but the value is "undefined", the output is "undefined ".

Summary

The above is what I learned and used Js for a while, in order to have a better understanding of it, but also to better grasp its application, so that in the process of learning the closure, I have some understanding and summary of the lexical scopes. There may be some differences between them and the actual JS interpretation engine, because I just analyzed this problem from the perspective of a beginner front-end developer rather than the system designer, hoping to help JavaScript developers understand the scope of this method!

From: http://js8.in/745.html

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.