Profile
We always define functions and variables in the program, and then use these functions and variables to build our system.
However, for the interpreter, how and where did it find the data (functions, variables)? What happens inside the interpreter when referencing an object?
Many ECMA scripting programmers know that variables and execution contexts are closely related:
var a = 10; // 全局上下文中的变量(function () { var b = 20; // 函数上下文中的局部变量})();alert(a); // 10alert(b); // "b" is not defined</pre>
Not only that, many programmers also know that the ECMAScript standard indicates that a separate scope can only be created by "function code" (one of the executable code types). For example, unlike C/s + +, the code block in ECMAScript for a loop cannot create a local context:
<pre>for (var k in {a: 1, b: 2}) { alert(k);}alert(k); // 尽管循环已经结束,但是变量“k”仍然在作用域中
Here's a detailed description of what happens when you declare variables and functions.
Data declaration
Since the variables are related to the execution context, it's time to know where the data is stored and how to get it. This mechanism is called a variable object:
A Variable object (in abbreviated FORM-VO) was a special object related with an execution context and which stores:
Variables (var, variabledeclaration);
function declarations (functiondeclaration, in abbreviated form FD);
and function Formal parameters
Declared in the context.
For example, you can use a ECMAScript object to represent a variable object:
<pre>VO = {};</pre>
Vo is also a property of an execution context:
<pre>activeExecutionContext = { VO: { // 上下文中的数据 (变量声明(var), 函数声明(FD), 函数形参(function arguments)) }};
An indirect reference to a variable (through the property name of Vo) allows only the variable object that occurs in the global context (the global object itself is a variable object, which is described later in this article). For other contexts, it is not possible to refer to Vo directly, because VO is the implementation layer.
The process of declaring new variables and functions is actually the process of creating new and variable and corresponding property and property values for the function name in Vo.
As shown below:
10; Test20;}; Test (+);
The variable object corresponding to the preceding code is as follows:
The variable object in the global context, VO (globalcontext) = { ten, test:};//Thevariable object in the context of the "test" function vo (functioncontext = { 20}; However, in the implementation layer (defined in the standard), the variable object is only an abstract concept. In the context of actual execution, Vo may not be called Vo at all, and the initial structure may be completely different.
Variable objects in different execution contexts
Some operations on variable objects (such as initialization of variables) and behavior are the same for all execution context types. From this point, it is more appropriate to represent the variable object as an abstract concept. The function context can also define additional information related to the variable object.
Of the variable instantiation process) ║ ╠══> globalcontextvo ║ Global) ║ ╚══ > Functioncontextvo (VO = = = AO, and is added)
The next step is to introduce this piece of content in detail.
Variable objects in the global context
First, it is necessary to define a global object.
A global object is an object that is created before entering any execution context; The object is in a singleton form, its properties are directly accessible anywhere in the program, and its life cycle terminates with the end of the program.
When a global object is created, properties such as Math,string,date,parseint and so on are also initialized, and some of the objects point to the global object itself-for example, in the DOM, the Window property on the global object points to the global object (however, Not all implementations are the same):
Global = { Math:, String: ... ... Window:global};
When referencing properties of global objects, prefixes can often be omitted because global objects are not directly accessible by name. However, the global object can be accessed through the this value on the global object, and by recursively referencing such as the Window object in the DOM:
String (//equals to global. String (10); //with prefix/= = = GLOBAL.WINDOW.A = = = GLOBAL.A = ten; global.b =;
Back to the global context of the variable object-here the variable object is the global object itself:
Global
An accurate understanding of this fact is necessary: it is for this reason that when a variable is declared in the global context, the variable can be referenced between the properties on the global object (for example, when the variable name is unknown in advance)
var a =new String ( ' test '); alert (a); //directly, is found in VO ( Globalcontext): "test" alert (window[ //indirectly via global = = = VO (globalcontext): " test "alert (a = = = THIS.A); //truevar AKey = ' a '; Alert (window[akey]); //indirectly, with dynamic property name: "test"
Variable objects in the context of a function
In the context of the execution of a function, VO is not directly accessible. It mainly plays the role of being called the active object (activation objects) (abbreviation: AO).
VO (functioncontext) = = = AO;
The active object is created when it enters the function context, and when initialized it creates a arguments property whose value is the arguments object:
AO = { arguments:};
The arguments object is a property on an active object that contains the following properties:
- callee--a reference to the current function
- Number of length--arguments
- Properties-indexes (numeric, converted to string) whose value is the value of the function parameter (in the argument list, from left to right). Number of properties-indexes = = Arguments.length;
The value of the properties-indexes of the arguments object is shared with the current (actually passed) parameter.
As shown below:
functionFoo(x, y, z) {Defines the number of function parameters (x, y, z) of alert (foo.length);3Number of arguments actually passed alert (Arguments.length);2The reference function itself alert (Arguments.callee = = = foo);TrueParameters are shared with each other alert (x = =arguments[0]);//true alert (x); //arguments[0] = 20; alert (x); //x = 30; alert (arguments[< Span class= "Hljs-number" >0]); ////however, for parameters not passed Z, // The index-property of the associated arguments object is not shared by Z = 40; alert (arguments[< Span class= "Hljs-number" >2]); //undefined arguments[2] = 50; alert (z); //40}foo (10, 20);
In the example above, there is a bug--parameter Z and arguments[2 in the current Google Chrome browser that is shared with each other.
Several stages of handling context code
At this point, it is the most important part of the article. The processing execution context code is divided into two phases:
- Go to execution context
- Execute code
Modifications to variable objects are closely related to these two phases.
It is important to note that these two processing stages are common behavior, regardless of the context type (both global context and function context are consistent).
Go to execution context
Once in the execution context (before executing the code), Vo is populated with some attributes (previously described):
- Formal parameters of the function (when entering the function execution context)
--a property of a variable object whose property name is the name of the formal parameter, whose value is the value of the argument, and for a parameter that is not passed, the value is undefined
- function declaration (functiondeclaration, FD)--a property of a variable object whose property name and value are created by a function object, and if the variable object already contains a property of the same name, replace its value
- Variable declaration (var,variabledeclaration)--a property of a variable object whose property name is the variable name and whose value is undefined; if the variable name and the function name already declared or the parameter name of the function are the same, the existing property will not be affected.
Look at the following example:
function Test (A, b) {
var C = 10;
Function d () {}
var e = function _e () {};
(function X () {});
}
Test (10); Pager
When the "test" function context is entered as a parameter of 10, the corresponding AO is as follows:
AO (Test) = { ten, undefined, undefined};
Note that the above AO does not contain the function "X". This is because the "x" here is not a function declaration but a function expression (functionexpression, abbreviated as FE), and the function expression does not affect VO. Although the function "_e" is also a function expression, as we have seen, because it is assigned to the variable "E", it can be visited by "E". The difference between a function declaration and a function expression is described in the fifth chapter--the function.
At this point, the first stage of processing the context code is covered, and then the second phase-the execution code phase-is introduced.
Execute code
At this point, the properties of the Ao/vo are already populated. (although most properties have not been given a true value, they are just the undefined value at the time of initialization).
To continue with the example above, by the execution of the code phase, the AO/VO will be modified to the following form:
ao[10; ao[' e '] =;
Again notice that the function expression "_e" is still in memory, because it is stored in the declared variable "E", and the same function expression "X" is not in the AO/VO: If you try to invoke the "X" function before or after the definition, an "x is defined" error occurs. An unsaved function expression can only be called if it is defined or recursive.
The following are more typical examples:
function; x//
In the above example, why is "X" printed out as a function? Why is it possible to access it before the declaration? And why not 10 or 20? The reason is that, according to the rules--when entering the context, Vo is filled with function declarations, and at the same stage, the variable declares "x", but, as mentioned earlier, the variable declaration is after the function declaration and the function parameter, and the variable declaration does not conflict with the function declaration and function parameters of the same name that already exists. Therefore, at the stage of entering the context, Vo fills in the following form:
VO = {}; vo[//found var x = ten; If the function "X" is not yet defined //Then "X" is undefined, but in our case //The variable declaration does not affect the function value with the same name vo[
Then, during the code execution phase, VO is modified to resemble the following:
vo[10; vo[;
As shown in the second and third alert.
As shown in the following example, the variable is stored in VO when it enters the context phase (so although the else code block will never be executed, and "B" is still in Vo):
if (true) { else { "B is not defined"
About variables
Most JavaScript-speaking and even JavaScript books often say: "There are two ways to declare a global variable, one is to use the var keyword (in the global context), and the other is to not have the Var keyword (anywhere)." And such a description is wrong. Keep in mind that:
Using the var keyword is the only way to declare a variable
The following assignment statement:
10;
Only new properties (not variables) are created on the global object. "Not a variable" does not mean that it cannot be changed, it is the concept of a variable in ECMAScript (it can then become a property of a global object, because VO (globalcontext) = = = Global, remember? )
The different points are as follows:
10; ;
The next step is to talk about VO and the changes to VO at different stages (into the context phase and execution code phase):
Enter the context:
VO = { undefined};
We see that there is no "B" at this stage, because it is not a variable and "B" appears only during the code execution phase. (However, this will not happen in our case because of the error before "B" appears)
Make a slight change to the above code:
Created at code execution//+, modified at code execution
There is a very important point here about variables: Unlike simple properties, variables are {dontdelete} that cannot be deleted, which means that it is not possible to delete a variable by using the delete operator.
10;alert (//10alert (///Truealert (///undefined 20;alert (///20alert (////Falsealert (/// Still
However, there is an exception, that is, in the "eval" execution context, you can delete a variable:
Eval (' var a = 10; '); Alert (//10alert (///Truealert (///undefined
With some debug tools, children's shoes that have tested these examples at the terminal should be noted: Firebug is also the code that uses eval to execute the terminal. Therefore, Var can also be deleted at this time.
Properties of the implementation layer: Parent Property
As previously described, it is not possible to directly access an active object under standard conditions. However, in some implementations, such as the well-known SpiderMonkey and Rhino, the function has a special property of the parent, which is a reference to the active object where the function was created (or a global variable object).
As shown below (Spidermonkey,rhino):
global = this; Ten; Foo//Global//True
In the above example, you can see that the function foo is created in the global context, corresponding to its parent property set to the global context of the variable object, such as: Global object.
However, it is not possible to get active objects in the same way in SpiderMonkey: Different versions behave differently, and the parent property of an intrinsic function returns null or a global object.
In rhino, getting an active object in the same way is allowed:
As shown below (Rhino):
Varglobal = this;var x =10; (functionFoo() {var y = 20; //The activation object of the "foo" context var AO = (function () {}). __parent__; print (AO.Y); //// __parent__ of the current activation//object is already the global object, //i.e. the Specia L Chain of variable objects is formed, //so-called, a scope chain print (ao.__parent__ = = = Global); //True print (ao.__parent__.x); //10}) ();
Summarize
In this article, we describe the objects that are related to the execution context. Hope, this article can help everyone, but also hope that this article can play a role in the doubts.
Extended Reading
- 10.1.3--variable Initialization
- 10.1.5--Global Objects
- 10.1.6--Active Object
- 10.1.8--Parameter Object
This article is translated from Dmitry A.soshnikov variable object
Zhao Jing/Songjingjin translation
JavaScript Internal principle Series-variable objects (Variable object)