Core Knowledge of javascript series (2)

Source: Internet
Author: User
A variable object is a container associated with the execution context. It is a special object closely associated with the context, including variables defined in the context and function declaration. Note that function expressions (different from function declaration) are not included in the variable object. The variable object is a... SyntaxHighlighter. all (); the variable object is a container associated with the execution context. It is a special object closely associated with the context, including variables defined in the context and function declaration. Note that function expressions (different from function declaration) are not included in the variable object. A variable object is an abstract concept. Theoretically, different context types indicate different objects. For example, in the global context, the variable object is the global context itself (that is why we can obtain the global variable through the Global Object attribute name). Copy the Code 1 var foo = 10; 3 function bar () {}// function declaration, FD4 (function baz () {}); // function expression, FE 6 console. log (7 this. foo = foo, // true8 window. bar = bar // true9); 11 console. log (baz); // ReferenceError, "baz" is not defined. The global context variable object (VO) will have the following attributes: Figure 7. the global variable object. global variable object we found that the function baz is not included in the variable object as a function expression. This is why a ReferenceError occurs when we obtain it outside the function. Note that this is different from other languages (c/c ++). In ECMAScript, only functions generate a new scope. Variables defined in the function scope and internal functions cannot be directly called outside the function, and they do not pollute the global variable object. After eval is used, we will enter an (eval's) Execution context, however, eval is used in a global variable object or in the caller's variable object (for example, eval is called by a function). What is the difference between the function and its variable object? In the function context, variable objects are represented as active objects. An activity object is generated when a function is activated (called) by a caller and a special object. It contains the form parameter and special arguments object (which is the ing of the form parameter but has index-properties ). In the context of a function, this activity object is used as a variable object. The variable object of a function is also a simple variable object, but it not only contains variables and function declarations, it also contains the form parameter and arguments object, and it is also called an activity object. See the following example: copy the Code 1 function foo (x, y) {2 var z = 30; 3 function bar () {}// FD4 (function baz () {}); // FE5} 7 foo (10, 20); copy the code and we will have the activity object (AO) Figure 8 in the context of the foo function. an activation object. figure 8. the activity object once again sees that the function expression baz is not included in the variable/activity object. The complete description of all clever situations in this topic (Variable escalation and function declaration) is found in Chapter 2. Variable object. we enter the next section. As we all know, in ECMAScript, we can use internal functions to obtain the variables of the parent function and the variables of the global context. Like the prototype chain discussed above, this is the so-called scope chain. The scope chain is a simple rule used to search for the list of objects marked in the context Code. It is similar to the prototype chain: if an object is not found in its scope (in its own variables/activity objects), it will go to the parent variable object to find it. In the context, the identifier indicates the variable name, function declaration, and form parameter. When a function uses variables that are not local variables (or local functions and parameters) in its code, such variables are called free variables and they are precisely searched, the scope is useful. In general, the scope chain is the list of all parent variable objects, plus the variables/activity objects of the function itself (at the beginning of the scope chain ), however, the scope chain also contains some other objects. For example, objects dynamically added to the scope chain during context code execution. For example, objects in with and catch clauses. When a identifier is parsed (searched), the scope chain starts to look for the activity object (if not found in the variable object) and gradually traces back to the top of the scope chain, same as the prototype chain, copy code 1 var x = 10; 2 (function foo () {3 var y = 20; 4 (function bar () {5 var z = 30; 6 // "x" and "y" are free variables. Search for 7 consoles in the next object in the bar scope chain. log (x + y + z); 8}) (); 9 })(); to copy the code, we use the implicit _ parent _ attribute (used to point to the next object in the scope chain) to infer the relationship between the scope chain objects. This method can be detected in real Rhino code. This technology is also used in ES5 lexical environment (called outer connection ). Another explanation of the scope chain is a simple array. Using _ parent _, we can use the following figure to explain this example (parent scope chain (note: In this article, it is a parent variable object that I think is wrong) saved in the [[Scope] attribute of the function): Figure 9. A scope chain. figure 9 the scope chain may be extended by the with and catch clause objects during code execution. Because these are simple objects, they may also have prototypes (and prototype chains ). This fact is that the scope chain search has become two-dimensional. (1) Consider the scope chain (2) the link of each scope-the depth of the prototype chain link (if there is a prototype in the Link process ). Copy code 1 Object. prototype. x = 10; 2 var w = 20; 3 var y = 30; 4 // Global object in SpiderMonkey, such as the variable object of the global context object from "object. prototype "inheritance, so when we point to the undefined global variable x, it will be found in the prototype chain. 5 console. log (x); // 10 6 (function foo () {7 // local variable of 'foo' 8 var w = 40; 9 var x = 100; 10 // "x" will be in "Object. prototype ", because {z: 50} inherits from it 11 with ({z: 50}) {12 console. log (w, x, y, z); //,} 14 // when the "with" object is deleted from the scope chain, "x" is searched in the variable object in the context of "foo", and the "w" variable also becomes the local variable 15 console. log (x, w); // how to obtain the global "w" variable 17 console in the host environment of our browser. log (window. w); // 2018}) copy the code. We have the following structure diagram (before we consider _ parent _ link, we should first consider _ proto _ chain) Figure 10. A "with-augm Ented "scope chain. 0" with-augment ". Note that not all global objects are inherited from Object. prototype. In SpiderMonkey, you can verify that if all the parent variables exist, there is nothing special about retrieving parent data from internal functions-we traverse the variables required for scope chain parsing. However, as we mentioned above, after a context ends, all its States and itself are destroyed. At this time, the internal function may return from the parent function. In addition, the returned function may be activated in another context. If the context of some free variables has already passed "gone", what will happen to this activation? In general, the concept that helps us solve this problem is called closure (lexical), which is directly related to the scope chain concept in ECMAScript. In ECMAScript, a function is a class object. This means that the function can be passed as a parameter to other functions (this is called "funargs" and the abbreviation of "functional arguments ). The function for obtaining "funargs" is called the higher-order function, which is also returned in other functions. Then the function that returns the function is called function valued functions (the function that returns the function value). The first form of a function parameter problem is the upward search problem. When a function that uses the free variables mentioned above returns data from another function. To get the variables of the parent context, even if the parent context is terminated. When an internal function is created, its parent Scope chain is saved in the [[Scope] attribute. When this function is activated, combined with the activity object and [[Scope] attributes, the Scope chain of the context of this function is formed. 1 Scope chain = Activation object + [[Scope] once again, pay attention to one major thing-at the time of creation-the function saves the parent Scope chain. Because the saved scope chain will be used in later function calls to find and copy the code function foo () {var x = 10; return function bar () {console. log (x) ;};}// "foo" returns a function that uses the free variable "x" var returnedFunction = foo (); // The global variable "x" var x = 20; // execute the returned function returnedFunction (); // 10. A static (lexical) scope is not used for copying 20 codes. We can see that the variable x is found in the [[Scope] attribute saved by the returned bar function. In general, in the above example, a dynamic scope stores the variable value of x as 20, instead of 10. However, ECMAScript does not have a dynamic scope. The second form of function parameter problems is the downward query problem. In this case, the parent scope may exist, but it may be saved with a fuzzy identifier. The question is: which scope should be used for the value of the identifier-the scope of static storage during function creation or the scope of dynamic parameters during execution (the scope of the caller )? To avoid such ambiguous scopes and generate closures, we decided to use static domain: Copy code 1/global x 2 var x = 10; 3 // global function 4 function foo () {5 console. log (x); 6} 7 (function (funArg) {8 // local x 9 var x = 20; 10 // It is not fuzzy here, because the global variable x we use is statically stored in [[Scope] of the foo function, rather than x12 funArg () in the Scope of the caller who activates the function; // 10, not 2013}) (foo); Copying code we can conclude that closures in languages must require static scopes. However, some languages provide static and dynamic scopes for programmers to choose-use closures or not. Because ECMAScript only has a static scope (for example, we solve the two function parameter problems ). ECMAScript uses the [[Scope] attribute of the function to fully support the closure. The following gives an accurate definition of the closure: the closure is a code block (in ECMAScript, this code block is a function) and the parent scope of static storage. Therefore, through the saved scope chain, the function can easily find the free variation. Note that each function is saved with [[Scope] during creation. Theoretically, all functions in ECMAScript are closures. You also need to remember the fact that many functions may have the same (this is really a common case, such as two internal/global functions) parent scope, in this case, variables stored in the [[Scope] attribute are shared among all functions with the same parent Scope chain. Changes to one closure variable will affect the variables read by another closure: Copy code 1 function baz () {2 var x = 1; 3 return {4 foo: function foo () {return ++ x ;}, 5 bar: function bar () {return -- x ;}6 }; 7} 8 var closures = baz (); 9 console. log (closures. foo (), // 210 closures. bar () // 1) copy the Code. This code can be used to explain: Figure 11. A shared [[Scope]. 0 shared [Scope] the confusion of constructing some functions in a loop is also related to this feature. When the cyclic counter is used in the constructed function, some programmers get some unexpected results when the same counter is used in the function. Now you know why-because all these functions have the same [[Scope], in this [Scope], the counter is the last count value. Copy code 1 var data = []; 3 for (var k = 0; k <3; k ++) {4 data [k] = function () {5 alert (k); 6}; 7} 9 data [0] (); // 3, but not 010 data [1] (); // 3, but not 111 data [2] (); // 3, but not 2 copy the code here there are some tips to solve these problems. One technique is to use an additional object in the scope chain: copy the code var data = []; for (var k = 0; k <3; k ++) {data [k] = (function (x) {return function () {alert (x) ;}) (k)} data [0] (); // 0 data [1] (); // 1 data [2] (); // 2 copy the code into the next part and consider executing the last attribute of context this. This value is a special object related to the execution context. Therefore, it can be named as a context object (the object activated during context execution). Any object can be used as the context's this value. I need to clarify some context-related descriptions, especially the this value, which is often incorrectly described as the attributes of the variable object. Remember: this is the attribute of the execution context, rather than the attribute of the variable object. this is never involved in the parsing process of the identifier. For example, the execution context in the Code directly obtains this without looking for the scope chain. The value of this is only determined by the context to be entered. In the global context, this is the global object itself (that is, this is equal to the Global Object): copy the Code 1 var x = 10; 3 console. log (4 x, // 105 this. x, // 106 window. x // 107); In the context of the function, the value of this may be different in every function call. This is provided by the caller through the call expression (function call method ). For example, in the following example, the foo function is called by the global context. Let's take a look at the example below for the same function code. Different call methods provide different this values. The code for copying the Code 1 // foo function remains unchanged. However, during each activation, this is a different 2 function foo () {3 alert (this ); 4} 5 // The caller activates the foo function and provides the value of this 6 foo (); // variable object 7 foo in the global environment. prototype. constructor (); // foo. prototype 8 var bar = {9 baz: foo10}; 11 bar, baz (); // bar12 (bar. baz) (); // also bar13 (bar. baz = bar. baz) (); // but here is global object14 (bar. baz, bar. baz) (); // also global object15 (false | bar. baz) (); // also global object16 var otherFoo = bar. baz; 17 otherFoo (); // again global object
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.