Document directory
- Classic case column Reproduction
- 6. Review classic cases
Lexical scope:The scope of a variable is determined by 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 get an in-depth understanding of lexical scopes and closures. Some Concepts and theoretical knowledge at the underlying layer during Javascript execution.
Classic case column reproduction 1. Classic Case 1
1/* a piece of code in the global (window) Field */2 function a (I) {3 var I; 4 alert (I); 5}; 6 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?
- Understand by definition: The local variables I and I are the same bucket (reference the same memory address ). In ecmascript, during function execution, the actual parameters of the input function are represented by an array inside the function. You can access this parameter array through the arguments object. The named parameter is only convenient, but not required. The javascript authoritative guide says:The arguments object has an extraordinary feature. When a function has a named parameter, the array element of the arguments object is a synonym for the local variable that stores the function parameter. Arguments [] arrays and named parameters are two different methods that reference the same variable. Changing the value of a parameter using the parameter name also changes the value obtained through the arguments [] array, and vice versa.. Therefore, you can think of a function parameter as a local variable that has been declared for a long time and has been assigned a value (if a parameter is input). Whether the written value is of the basic type or reference type, the values of the arguments [] array are changed. Therefore, the code in the first row of the case above defines a local variable with the same name as I and is not assigned a value.Ecmascript is specified in the same scope,If repeatedDeclare a variable and assignThe initial value is only the role of a value assignment statement. If a variable is declared repeatedly but there is no initial value, it will not have any impact on the original variables.. For example:
Obviously, when the statement var I; is not executed, the value of I is 10. Another way is to do "pre-resolution" for the [Var] variable. That is to say, before the function is executed, the [Var] variable has been declared but not assigned a value, when the VaR statement is executed, it is only a value assignment. Therefore, when a function declares a local variable, it is generally written at the beginning of the function body to avoid affecting understanding, such as case 4.
2. Classic Case 2
1/* code segment in the global (window) Field */2 function a (I) {3 alert (I); 4 alert (arguments [0]); // arguments [0] should be the form parameter I5 var I = 2; 6 alert (I); 7 alert (arguments [0]); 8}; 9 A (10 );
Q: What will the above Code output? (10, 10, 2, 2)
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
1/* code segment in the global (window) Field */2 function a (I) {3 var I = I; 4 alert (I); 5 }; 6 A (10 );
Q: What will the above Code output? (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
1/* code segment in the global (window) Field */2 var I = 10; 3 function a () {4 alert (I); 5 var I = 2; 6 alert (I); 7}; 8 ();
Q: What will the above Code output?
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?
If you see the above examples, you may make a mistake. The reason is: we can quickly write a method, but in the end, how is the internal execution 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.
Parsing process
1. 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.
Javascript execution process. If a Document Stream contains multiple script code segments (JavaScript code separated by the script tag or the introduced JS file), the running sequence is as follows:
Step 1. Read the first code segment (the JS execution engine does not execute the program in one row, but analyzes and executes the program in one row)
Step 2. Perform lexical analysis and syntax analysis. If there is a mistake, the system reports a syntax error (such as mismatched brackets) and jumps to Step 5.
Step 3. Perform "pre-resolution" on the [Var] variable and [function] definition (no error will be reported because only the correct declaration is parsed)
Step 4. Execute the code segment. If there is an error, an error is returned (for example, the variable is undefined)
Step 5. If there is another code segment, read the next code segment and repeat Step 2.
Step 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.
- Parsing: A Legal syntax analysis tree is constructed through syntax analysis and pre-resolution.
- Execute: execute a specific function. When the JS engine executes each function instance, it creates an execution environment (executioncontext) and an 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.
- Syntaxtree intuitively shows information about this Code. The JS engine creates tables to record the variables in each method ), method set (functions) and scope (Scope)
- The execution environment (executioncontext) can be understood as an object that records the current method [external description information], the type, name, parameter, and activity object of the method to be executed)
- Activeobject can be understood as an object that records the internal execution information of the current method, and records the internal variables and nested functions), real parameters (arguments), scope chain (scopechain) and other required information for execution, including the internal variable set (variables), nested function set (functions) is directly copied from the syntax analysis tree created in step 1.
- Lexical scope: the scope of a variable is determined during 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
5. Function running process
- In the execution context stage, the function initializes various variables and records them in an internal variable object (variable object. The variables recorded in this variable object are listed as follows: (a) actual parameters of the function; (B) internal function declaration; (c) internal variable set. At this time, the first two variables have specific values, and the internal variable set value is not undefined.
- CreateReal parameter (arguments)Object, real parameters with the same name, and the reference relationship between the form 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.
6. Review classic cases
Case 1, 2, 3: according to [in a method, a real parameter with the same name is referenced between the form parameter and the variable, that is to say, the processing of the JS engine is to reference the same memory address for both variables with the same name and form parameters. This is why modifying arguments in Case 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 they are not found, search for them in the activeobject indicated by the scopechain attribute in the execution environment, until Global Object (window)], so in case 4, because the definition of variable I is found in the current activeobject, the value is "undefined ", therefore, "undefined" is output directly.