Introduction
During JavaScript programming, we can't avoid declaring functions and variables to build our system successfully. But how and where can the interpreter find these functions and variables? What happened when we reference these objects?
Original release: Dmitry A. soshnikov
Release date:
Russian address: http://Dmitrysoshnikov.com/ecmascript/ru-chapter-2-variable-object/
Dmitry A. soshnikov
Release date: 2010-03-15
English address: http://Dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/
Some sentences that are difficult to translate refer to justinw's Chinese translation.
Most ecmascriptProgramIt should be known that the variables are closely related to the execution context:
VaRA = 10;//Variables in the Global Context
(Function(){
VaRB = 20;//Local variables in the function Context
})();
Alert ();//10
Alert (B );//The global variable "B" is not declared
In addition, many programmers know that the current ecmascript specification specifies that the independent scope can only pass the Function )"CodeType execution context creation. That is to say, compared with C/C ++, The for loop in ecmascript cannot create a local context.
For(VaRKIn{A: 1, B: 2 }){
Alert (k );
}
Alert (k );//Although the loop has ended, the variable k is still in the current scope.
Let's take a look at the details we found when declaring the data.
Data Declaration
If the variable is related to the execution context, the variable should know where its data is stored and how to access it. This mechanism is called a variable object ).
A variable object (VO) is a special object related to the execution context. It stores the following content declared in the context:
Variable (VaR, Variable Declaration );
Function declaration (functiondeclaration );
Function Parameters
For example, we can use a common ecmascript object to represent a variable object:
VO = {};
As we said, Vo is the property of the execution context ):
Activeexecutioncontext = {
VO :{
//Context Data (VAR, FD, function arguments)
}
};
Only the variable objects in the global context can be indirectly accessed through the VO attribute name (because in the global context, the global object itself is a variable object, which will be detailed later ), in other contexts, you cannot directly access the VO object because it is only an implementation of the internal mechanism.
When we declare a variable or function, it is no different from when we create a new VO attribute (that is, there are names and corresponding values ).
For example:
VaRA = 10;
FunctionTest (x ){
VaRB = 20;
};
Test (30 );
The corresponding variable object is:
//Global context variable object
VO (globalcontext) = {
A: 10,
Test: <referenceFunction>
};
//Variable object in the test function Context
VO (test functioncontext) = {
X: 30,
B: 20
};
Variable objects are just an abstract concept at the specific implementation level (and in specifications. (Essentially, in the context of specific execution, the VO name is different and the initial structure is different.
Variable objects in different execution contexts
For all types of execution contexts, some operations (such as variable initialization) and actions of the variable object are common. From this perspective, it is easier to understand the variable object as an abstract basic thing. The additional content related to the variable object is also defined in the function context.
Abstract variable object VO (common behavior during variable initialization)
Bytes
Globalcontextvo
Merge (Vo =This=== Global)
Bytes
Function context variable object functioncontextvo
(Vo = AO, and <arguments> and <formal parameters> are added)
Let's take a closer look:
Variable objects in the Global Context
First, we need to give a clear definition to the global object:
A global object is an object created before any execution context is entered;
This object only has one copy, and its attributes can be accessed anywhere in the program. The life cycle of the global object ends at the moment when the program exits.
The math, String, date, and parseint attributes of the global object are initialized in the initial creation phase, you can also create additional objects as attributes (which can point to the global object itself ). For example, in Dom, the window attribute of the global object can reference the global object itself (Of course, not all implementations are like this ):
Global = {
Math: <...>,
String: <...>
...
...
Window: Global//Reference itself
};
Prefix is often ignored when accessing global object attributes, because global objects cannot be accessed directly by name. However, we can still access global objects through this in the global context. We can also reference ourselves recursively. For example, window in Dom. To sum up, the code can be abbreviated:
String (10 );//Is global. String (10 );
//Prefix
Window. A = 10;//=== Global. Window. A = 10 === global. A = 10;
This. B = 20;//Global. B = 20;
Therefore, return to the variable object in the Global Context -- here, the variable object is the global object itself:
VO (globalcontext) = global;
It is very necessary to understand the above conclusion. Based on this principle, we can access it indirectly through the attributes of the global object in the global context. (For example, do not know the variable name beforehand ).
VaRA =NewString ('test ');
Alert ();//Direct access. In VO (globalcontext), find: "test"
Alert (window ['a']);//Access via global indirectly: Global === VO (globalcontext): "test"
Alert (A =This. );//True
VaRAkey = 'a ';
Alert (window [akey]);//Indirect access by dynamic attribute name: "test"
Variable objects in the function Context
In the context of function execution, Vo cannot be directly accessed. At this time, the active object (AO) plays the role of VO.
VO (functioncontext) = AO;
An active object is created when the context of the function is entered. It is initialized through the arguments attribute of the function. The value of the arguments attribute is an arguments object:
Ao = {
Arguments: <Argo>
};
An arguments object is an attribute of an activity object. It includes the following attributes:
- Callee-reference to the current function
- Length-Number of actually passed parameters
- The properties-indexes (an integer of the string type) attribute value is the parameter value of the function (arranged from left to right by the parameter list ). The number of elements in properties-indexes is equal to that in arguments. length. properties-indexes and the actually passed parameters are shared.
For example:
Function Foo (x, y, z ){
// Number of declared function parameters arguments (x, y, z)
Alert (FOO. Length ); // 3
// Number of actually passed parameters (only x, y)
Alert (arguments. Length ); // 2
// The callee parameter is the function itself.
Alert (arguments. callee = Foo ); // True
// Parameter sharing
Alert (x = arguments [0]); // True
Alert (X ); // 10
Arguments [0] = 20;
Alert (X ); // 20
X = 30;
Alert (arguments [0]); // 30
// However, the input parameter Z is not shared with the parameter's 3rd index values.
Z = 40;
Alert (arguments [2]); // Undefined
Arguments [2] = 50;
Alert (z ); // 40
}
Foo (10, 20 );
The code in this example has a bug in the current Google Chrome browser-even if the Z, Z, and arguments [2] parameters are not passed, they are still shared.
Two phases of processing the context code
Now we have reached the core point of this article. The execution context code is divided into two basic stages for processing:
- Enter execution Context
- Execute Code
Changes to variable objects are closely related to these two phases.
Note: The processing of these two phases is a general action and is irrelevant to the context type (that is, the global context and function context are the same ).
Enter execution Context
When you enter the execution context (before code execution), Vo contains the following attributes (as mentioned earlier ):
All parameters of the function (if we are in the context of function execution)
-The property of a variable object consisting of a name and a corresponding value is created. If no corresponding parameter is passed, the attributes of a variable object consisting of the name and undefined value will also be created.
All function declarations (functiondeclaration, FD)
-The property of a variable object consisting of a name and a corresponding value (function object) is created. If the variable object already has an attribute with the same name, the property is completely replaced.
All variable declarations (VAR, variabledeclaration)
-Attributes of a variable object composed of the name and the corresponding value (undefined) are created. If the variable name is the same as the declared parameters or functions, the variable declaration does not interfere with the existing attributes.
Let's take an example:
FunctionTest (a, B ){
VaRC = 10;
FunctionD (){}
VaRE =Function_ E (){};
(FunctionX (){});
}
Test (10 );//Call
When entering the context of the test function with the parameter 10, ao performs as follows:
AO (TEST) = {
A: 10,
B: undefined,
C: undefined,
D: <reference to functiondeclaration "D">
E: Undefined
};
Note that AO does not contain the function "X ". This is because "X" is a function expression (functionexpression, abbreviated as Fe) rather than a function declaration. function expressions do not affect vo. In any case, the function "_ e" is also a function expression, but as we will see below, because it is assigned to the variable "E ", therefore, it can be accessed by the name "E. The difference between the function declaration functiondeclaration and the function expression functionexpression will be discussed in detail in chapter 15th functions. You can also refer to Chapter 2nd of this series to reveal the name of the function expression.
After that, the second stage of processing the context code is executed.
Code Execution
In this period, AO/Vo already has attributes (however, not all attributes have values, and most attribute values are still the default undefined values ).
In the previous example, AO/Vo was modified as follows during code interpretation:
AO ['C'] = 10;
AO ['E'] = <reference to functionexpression "_ e">;
Note that since functionexpression "_ e" is saved to the declared variable "E", it still exists in the memory. Functionexpression "X" does not exist in AO/VO. That is to say, if we want to call the "X" function, no matter before or after the function is defined, an error "X is not defined" will occur. unsaved function expressions can be called only in their own definitions or recursion.
Another typical example:
Alert (X );//Function
VaRX = 10;
Alert (X );//10
X = 20;
FunctionX (){};
Alert (X );//20
Why does the first alert "X" return a function, and it still accesses "X" before "X" is declared? Why not 10 or 20? Because, according to the canonicalized function declarationEnter ContextWhen entering the context, there is also a variable Declaration "X", as we said in the previous stage, the variable declaration follows the function declaration and the formal parameter declaration in order, andEnter ContextStage, the variable declaration does not interfere with the existing function declaration with the same name or form parameter declaration in Vo. Therefore, when entering the context, the VO structure is as follows:
VO = {};
VO ['X'] = <reference to functiondeclaration "X">
//Find var x = 10;
//If function "X" is not declared
//At this time, the value of "X" should be undefined.
//However, in this case, the variable declaration does not affect the function value of the same name.
VO ['X'] = <the value is not disturbed, stillFunction>
Then, in the code execution stage, Vo makes the following changes:
VO ['X'] = 10;
VO ['X'] = 20;
We can see this effect in the second and third alert.
In the following example, we can see that the variables are put into VO at the context stage. (Because, although some else code will never be executed, the variable "B" still exists in Vo .)
If(True){
VaRA = 1;
}Else{
VaRB = 2;
}
Alert ();//1
Alert (B );//Undefined. The value of B is not declared.
About Variables
GenerallyArticleBooks related to JavaScript all claim that "a variable can be declared whether the VaR keyword is used (in the Global Context) or the VaR keyword is not used (anywhere ". Remember, this is an incorrect concept:
Variables can only be declared by using the VaR keyword at any time.
The above assignment statement:
A = 10;
This only creates a new attribute for the Global Object (but it is not a variable ). "Not a variable" does not mean that it cannot be changed, but does not comply with the variable concept in the ecmascript specification, so it is "not a variable" (the reason why it can become a global object attribute, this is because VO (globalcontext) = Global. Do you still remember this ?).
Let's take a look at the specific differences through the following examples:
Alert ();//Undefined
Alert (B );//"B" is not declared
B = 10;
VaRA = 20;
The root cause is still vo and enters the context and code execution phases:
Enter the context stage:
Vo = {
A: Undefined
};
We can see that "B" is not a variable, so there is no "B" at this stage ", "B" will only appear in the code execution phase (but in our example, an error has occurred before it reaches ).
Let's change the example code:
Alert ();//Undefined. Everyone knows this,
B = 10;
Alert (B );//10. code execution stage Creation
VaRA = 20;
Alert ();//20. code execution stage Modification
There is also an important knowledge point about variables. Compared with a simple attribute, a variable has a feature (attribute): {dontdelete}. This feature means that the delete operator cannot be used to directly Delete the variable attribute.
A = 10;
Alert (window. );//10
Alert (DeleteA );//True
Alert (window. );//Undefined
VaRB = 20;
Alert (window. B );//20
Alert (DeleteB );//False
Alert (window. B );//Still 20
However, this rule does not have to go out of context, that is, the eval context. The variable does not have the {dontdelete} feature.
Eval ('var A = 10 ;');
Alert (window. );//10
Alert (DeleteA );//True
Alert (window. );//Undefined
When you use a debugging tool (for example, firebug) to test the instance, you must note that firebug also uses eval to execute your code on the console. Therefore, the variable property also does not have {Dontdelete} Feature, which can be deleted.
Special implementation: _ parent _ attribute
As mentioned above, according to the standard, activity objects cannot be directly accessed. However, some specific implementations do not fully comply with this provision. For example, in the implementation of spidermonkey and rhino;, the function has a special attribute _ parent __, you can use this property to directly reference an activity object (or a global variable object) and create a function in this object.
For example (spidermonkey, Rhino ):
VaRGlobal =This;
VaRA = 10;
FunctionFoo (){}
Alert (FOO. _ parent __);//Global
VaRVo = Foo. _ parent __;
Alert (VO. );//10
Alert (Vo = global );//True
In the above example, we can see that the function foo is created in the global context, so the attribute _ parent _ points to the global context variable object, that is, the global object.
However, it is impossible to access the active object in the same way in spidermonkey: in different versions of spidermonkey, the _ parent _ of the internal function sometimes points to null and sometimes to global objects.
In rhino, you can access activity objects in the same way.
For example (Rhino ):
VaR Global = This ;
VaR X = 10;
( Function Foo (){
VaR Y = 20;
// Activity object in the context of "foo"
VaR Ao = ( Function () {}). _ Parent __;
Print (AO. y ); // 20
// The _ parent _ of the current active object is an existing global object.
// The special chain of the variable object is
// So we call it the scope chain.
Print (AO. _ parent _ = global ); // True
Print (AO. _ parent _. X ); // 10
})();
Summary
In this article, we have learned in depth the objects related to the execution context. I hope this knowledge can help you solve some problems or confusions you have encountered. As planned, in subsequent chapters, we will explore the scope chain, identifier resolution, and closure.
If you have any questions, I am very happy to help you answer them in the following comments.
Other references
- 10.1.3-variable instantiation;
- 10.1.5-Global object;
- 10.1.6-activation object;
- 10.1.8-arguments object.
Transferred from: Uncle Tom