Variable object of JavaScript series

Source: Internet
Author: User
Tags end eval execution expression functions variables string version

Generally in programming, we will define functions and variables to successfully construct our system. But how does the parser find the data (functions, variables)? What happens when we refer to the object we need?

Many ECMAScript programmers know that variables are closely related to the context in which they are executed:


var a=10;//variables in global context
(function () {
Local variables in the context of Var b=20;//function
})();
alert (a);//10
alert (b);//"B" not defined



Of course, many programmers know it. Under the current specification version, the scope of the quarantine can only be generated by the execution context of the "function" code. Unlike C + +, for example, a For loop statement block in ECMAScript cannot produce a partial execution context:

For (var k in {A:1,b:2}) {
Alert (k);
}
Alert (k);//Even if the loop ends, the variable ' k ' is still in scope

Let's take a look at the more details that happen when we declare our data.
Data declaration

If the variables are closely related to the execution context, you should know where the data is stored and how to get the data. This mechanism is called a variable object.

A variable object (VO) is a special object that is closely associated with the execution context and its storage location:

Variable (var, variable declaration);
function declaration (FD);
function parameter;

is declared in the context. Note that the lexical environment pattern is substituted for the variable object in EC5.

Theoretically, the variable object can be represented as a regular ECMAScript object: vo={}; As we said, VO is an attribute of the execution context:

activeexecutioncontext={
vo:{
Context data (var,fd,function arguments)
}
};

You cannot refer directly to variables in general. A variable object that can refer to the global context only (through the attribute name of VO) (the global object is his own variable object). As for other execution contexts, it is not possible to refer to VO directly, it is merely a purely mechanism for the realization of the level.

When we declare a variable or function. We have nothing else to do except construct Vo's attributes that contain variable names and variable values. Like what:

var a=10;
function test (x) {
var b=20;};
Test (30);

The corresponding variable objects are:


Variable objects in the Global environment
VO (Globalcontext) ={
A=10,
Test:<reerence to Function>
};
Variable object for the context of the "test" function
VO (test Functioncontext) ={
X:30,
B:20
};



But in the execution phase (under the standard), the variable object is an abstract essence. In a specific execution context, Vo is named differently and has a different initial structure.
Variable objects in different execution contexts

Some operations of variable objects, such as variable assignment, and behavior are the same in all execution context types. From this point of view, it is convenient to represent variable objects as an abstract basic concept. The function context can also define some additional information related to a variable object.


Abstratvo (Generic procedure for variable object instantiation)

╠══> Globalcontextvo
║ (VO = = This = = Global)

╚══> Functioncontextvo
(VO = = AO, <arguments> object and <formal parameters> are added)



Let's discuss it in detail below.
Global Context Variable Object

Here, you should first give the definition of the global object: A Global object is an object that has been constructed before it enters any execution context; The global object is unique (translator: single case mode), where it can be obtained from anywhere in the program, and its lifecycle ends with the end of the program.

The constructed global object is initialized by attributes such as Math,string,date,parseint. It can also be initialized with additional objects that can reference the global object itself. For example, in a BOM, the Window property of a global object points to a global object (however, not all implementations are like this)


global={
Math:<...>,
String:<...>,
....
....
Window:global
};



When referencing a global object property, the prefix is usually omitted because the global object cannot be obtained directly from the name. It may be obtained through the this value in the global context, or it can be obtained by recursively referencing itself, such as window in the BOM, which can be abbreviated as:

String (10);//Represents Global. String (10);
Have a 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-the variable object here is the global object itself: VO (Globalcontex) ===global;

For these reasons it is necessary to understand precisely the fact that a variable declared in the global context can be referenced indirectly through the properties of the global object (for example, the variable name is unknown).


var a=new String (' test ')
alert (a);//Direct reference, in VO (globalcontext): "Test"
Alert (window[' a ']);//Indirect reference ===vo (Globalcontext): "Test"
alert (A===THIS.A);//true
var akey= ' a ';
Alert (Window[akey]);//indirect reference, through the dynamic property name: "Test"


Variable object for function context

For a function execution context-vo is not directly acquired, its role is played by the active object (AO). VO (Functioncontext) ===ao; When entered into a function context, the active object is generated. and initialized by the arguments property of the value arguments object.

1 ao={arguments:<arguments object>}

The arguments object is the property of the active object. It contains the following properties:

A reference to the callee--function itself;
length--the number of actual parameters;
Properties-indexes (integer, converted to character) whose value is the value of the function argument (the argument list is left to right). Properties-indexes==arguments.length. That is, the Parameter object's Properties-indexes value and the current (actual incoming value) of the formal parameters are shared



function foo (x, y, z) {
Number of defined function arguments (x, y, z)
alert (foo.length); 3
Actual number of parameters (only X, y)
alert (arguments.length); 2
Reference to 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 Index property of an z,arguments parameter object that is not passed is not shared
z = 40;
Alert (arguments[2]); Undefined
ARGUMENTS[2] = 50;
alert (z); 40
}



There is a vulnerability in the low version of Google Browser for parameter sharing. In the EC5. The concept of the active object has been replaced by the public and single case pattern of the lexical environment.
Stages of handling context code

Now we're going to focus on the article, which is divided into two stages for handling execution context code:

into the implementation context;
Executes the code.

The modification of variable objects is closely related to these two phases. It should be noted that the processing of these two phases is a generic behavior and is independent of the context type (that is, the process is equal to both execution contexts-functions and global)
Enter execution context

When entering the execution context (before the code executes), Vo is populated with the following attributes, which they have already mentioned in the previous article.

For each parameter of a function (if we have entered the function execution context)---A Variable object property with a name and parameter value is created, and the argument has not yet passed the value--that is, the property that contains the parameter name and whose value is undefined is created.
For each function declaration (FD)---a property containing the name and value of the function object is created, and if the variable object already contains a property of the same name, overwrite his value and attributes;
For each variable declaration---a property with a variable name and a value of undefined is created, and if the variable name is the same as the name of the formal parameter or function already declared, the variable declaration cannot conflict with the existing property (translator Note: This variable name is not available, in other word).

Let's look at the following example;


function test (a,b) {
var c=10;
Function d () {};
var e=function _e () {};
(function X () {});
}
Test (10)



When you enter the context of the test function that contains argument 10, AO is as follows:


AO (Test) = {
A:10,
B:undefined,
C:undefined,
D: <reference to Functiondeclaration "D" >
e:undefinedhttp://i.cnblogs.com/editposts.aspx?postid=3711963
};



Note that this AO does not contain function x, because x is not a function declaration but a function expression (FE), and the expression does not affect VO. However, the function _e is also a function expression, but we will find it in VO because it is assigned to the variable e, which is obtained by E. function declarations and function expressions are discussed in detail later. These end up in the second phase of dealing with context code-the code execution phase.
Code execution

At this point, Ao/vo already contains these attributes (although not all of the attributes have the true value we passed, but most of them already have the initial value undefined). In the same example, when the code is parsed, the following corrections are AO/VO:

Ao[' C '] = 10;
Ao[' e '] = <reference to Functionexpression "_e" >;

We also note that this function expression _e only exists in memory because it is saved in the declared variable E. But the function expression x isn't in the AO/VO, and if we call the X function before or after the definition, we get the error: "X" is not defined. An unsaved function expression can only be invoked where it is defined or recursively called.

A classic example:


Alert (x)//function X () {}

var x=10;
alert (x);//10
x=20;
function X () {}
alert (x);//20



Why is it that a pop-up x is a function and can be acquired before the declaration is made? Why not 10 or 20? Because, according to the rules-before entering the context Vo is populated by the function declaration. At the same time, there is a variable declaration x, but as we mentioned above, the semantic variable declaration phase is after the function declaration and the formal parameter declaration. In this period the variable is not yet conflicting with the declared function and parameter name. Therefore, when entering the VO context:

vo={};
vo[' x ']=<reference to functiondeclaration ' x ' >
var x=10;
If function "X" is not yet defined, "X" is undefined. In this case, however, a variable declaration cannot interfere with a function of the same name.
vo[' x ']=< value has not been destroyed, still is function>

In the code execution phase, VO fixes the following

vo[' x ']=10;
vo[' x ']=20;

We are in the second and third alert out of the results.

In the following example we see again in the context stage that the variable is placed in VO (therefore, else is never executed, but nevertheless, the variable B is still in VO):


if (true) {
var a=1;
}else{
var b=1;
}
alert (a);//1
alert (b);//undefined but not "B are not defined"


About variables

Many articles about JavaScript, even books, say: "It is possible to use the VAR keyword (in the global Execution environment) and to declare global variables without using the var keyword (anywhere)." It's not really like that. Keep in mind that variables can only be declared through the VAR keyword.

Assignment like this: a=10; just creates a new property (not a variable) for the global object. In this sense "not the variable" is not immutable, but under the ECMAScript variable concept (because of VO (Globalcontext) ===global, do we remember? ), it becomes a property of the global object.

The difference is below (show by example)

alert (a);//undefined
alert (b);//b is not defined
b=10;
var a=20;

All depend on VO and his revision phase (into the execution context and code execution phase):

Enter Context:

1 VO = {a:undefined};

We see no b here at this stage because he is not a variable. b only occurs during the Code execution phase (in which case there is no error). We modify the code as follows:

alert (a); Undefined, we know why
b = 10;
alert (b); Created at Code execution
var a = 20;
alert (a); Modified at Code execution

There is a more important point about variables here. Variables differ from simple properties, with the {Dontdelete} attribute, which means that a variable cannot be deleted by the delete operator:


a=10;
alert (WINDOW.A);//10
Alert (delete a);//true
alert (WINDOW.A);//undefined
var b=20;
alert (window.b);//20
Alert (delete b);//false
alert (window.b);//still 20



Remember that in ES5 {dontdelete} is renamed [[Configureable]] and can be managed manually through the Object.defineproperty method. However, there is an execution context in which this rule does not work. He's the eval context: the variable no longer sets the {Dontdelete} property:

Eval (' var a = 10; ');
alert (WINDOW.A); 10
Alert (delete a); True
alert (WINDOW.A); Undefined

For those debugging tools that validate these examples in the console, such as Firebug: Remember, Firebug also uses eval on the console to execute your code. Therefore, these variables also do not have the {Dontdelete} attribute and can be deleted.
Features of the implementation layer: _parent_ Properties

We have noticed that under the standard circumstances. It is not possible to get the active object directly. However, in some implementations, such as SpiderMonkey and Rhino. The function has a special attribute _parent_. He can reference the active object that has been generated in the function.

Example (SpiderMonkey, Rhino):


var global=this;
var a=10;
function foo () {}
alert (FOO._PARENT_);//global
var Vo=foo._parent_;
alert (VO.A);//10
alert (vo===global);//true



In the above example we see that function foo () is constructed in the global context, whereby his _parent_ property is set to the global context variable object, which is the global object. It is not possible, however, to get the active object in the same way: according to different versions, the _parent_ of the internal function returns null or Global object (SpiderMonkey).

In rhino, the active object is allowed to be obtained in the same way:


var global=this;
var a=10;
(function foo () {
var y=20;
Active object for the "Foo" function context
var ao= (function () {}). _parent_;
alert (AO.Y);//20
The _parent_ of the currently active object has become a global object. Such a special chain of variable objects is formed, which is called the scope chain
alert (ao._parent_===global);//true
alert (ao._parent_.x);//10
})()


Summarize

In this article we continue to delve into the objects associated with the execution context. I hope these materials are useful and clear about some of the areas that you previously felt were ambiguous. Future plans, in the following chapters, will refer to the scope chain, identify the identifier, and ultimately the closure.



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.