After being used to OOP programming, I will find many strange and strange phenomena (such as closures) in the Javascript world. I spent a lot of energy studying the root of these strange phenomena and finally found: the scope originated from javascript is not block-level scope, and it also has a set of scope-chain-based identification lookup mechanism. Most of the content in this article comes from the Internet, which has been organized and improved.
- Garbage collection algorithms used by the Javascript engine and DOM: reference count
Javascript and DOM have their own garbage collectors, which work well independently and may cause problems when working together. The defect of the reference counting algorithm is that Javascript objects and DOM objects reference each other cyclically, resulting in the reference counting of each other never being 0. The Garbage Collector cannot correctly recycle these objects involved in the circular reference, memory leakage (Memory Leak ). Closure is a circular reference of "large ". If you are interested in garbage collection, you can take a look at the history of garbage collection.
- Lexical scope (generally referred to as scope), with/eval
In short, the scope of javascript is divided by function. After reading this article, you will understand the Javascript Running Mechanism in the lexical scope. The with/eval special cases will disrupt the scope, that is, the so-called dynamic scope)
- Scope Chain)And Identity Search Mechanism
The scope chain is a linked list (data structure). It is the soul of Javascript. Only by understanding it can we understand the strange phenomenon in the Javascript world. The scope chain is linked by activity objects.
The identification search mechanism will be explained later based on the principle of function execution.
- Activity object)
Many people in China call an object. this document uses the English call obejct (but I personally think it is better to translate it into an "activity object" and it will not be confused with the object referred to by this .)
For objects in a very special javascript engine, the ECMAScript standard term is called activation object (activity object ). Multiple call objects and Global Objects form a scope chain)
- The essence of functions (famous functions, anonymous functions) and [[scope] attribute functions of functions are a special reference type in javascript, it inherits from the objects at the top of the javascript world. Its type is Function and belongs to the constructors of other common reference types.
When defining a function, the Javascript engine assigns a value to a private [[scope] attribute of the function object. Theoretically, only the js engine can access the function itself (that is: in general, it cannot be accessed through syntax, but there is a _ parent ___ accessible in Firefox ). The [[scope] attribute of an anonymous function points to the context object when an anonymous function is defined. A famous function is the same as an anonymous function, it also points to a Javascript Object (inherited from obejct) at the top of the [scope] attribute. prototype), this object is linked to the Scope Chain when the function is defined. It has an attribute that is the name of the function, this ensures that the code inside the function can access its own function name without error for recursion.
When defining a function, the javascript parserScope chain)When it is set to define the function, the function is located in the "Environment". If the function is a global function, only the window object is in scope chain.
For more information about how to execute a function, see the following description.
- Closure (closure)
All javascript Functions are closures, but only nested closures (also the form we often discuss) can reflect the strength of this javascript feature. Read this article:A deep understanding of the JavaScript closure (closure)
- How is the scope chain and activity object formed during function execution and its relationship with closures?
1. When the javascript parser is started, it will initialize and create a global object. This global object has some predefined global variables and global methods, such as Infinity, parseInt, Math, global variables defined in all programs are the attributes of this global object. In client javascript, Window is the global object of this javascript.2. When javascript executes a function, it generates an object called call object. The local variables and function parameters in the function become the attributes of the call object, to avoid overwriting global variables with the same name.
3. Each time the javascript parser executes a function, it creates an execution context execution environment for the function. In this function execution environment, the most important thing is the scope chain of the function, this is an object chain, which consists of global objects and activity objects. For the specific composition process of the object chain, see the following description.
4. Identity Search Mechanism: When javascript queries the value of variable x, it checks the first object in the scope chain, it may be a function call object or a global object (such as window). If the x attribute is defined in the object, the return value is returned. Otherwise, check whether the next object in the scope chain defines the x attribute, not found in the scope chain, and finally returned undefined.
5. When javascript executes a function, it first uses the scope defined by this function as its scope chain, and then creates a call object, which is placed at the top of the scope chain, the function parameter and all local variables declared by the internal var will become the attributes of the called object.
6. the keyword "this" points to the caller of the method, rather than the property of the called object. this in the same method may point to different objects in different function calls.
7. The Call Object as a Namespace. Use the activity object as a namespace to avoid naming pollution.
(Function (){
// All local variables declared with var in the method body exist in the form of attributes of the live object created during method call.
// Avoid naming conflicts with global variables.
})();
8. All functions in javascript are a closure, which is powerful only when a nested function is exported out of the scope defined by it. If you understand the closure, you will understand the scope chain and activity object during function execution to truly master javascript.
9. Micro-world of nested closures: when a reference to an internal function is saved to a global variable or an object attribute outside the nested closure, in this case, this internal function has an external reference and has an attribute pointing to this internal function in the activity object of the function called in its periphery. Because other objects reference this internal function, after the peripheral function is called once, the created activity object will continue to exist, it will not be recycled by the garbage collector (because the reference count is not 0). The parameters and local variables of the internal function will be maintained in this active object, javascript code cannot directly access this activity object in any form, but this activity object is part of the scope chain created when an internal function is called and can be accessed and modified by internal functions.
Finally, we introduced a strange phenomenon: the following code, why is the title always 6 when you move the mouse over li, rather than the expected number? Check whether you can explain the cause of this phenomenon based on the above knowledge. Tip: Variable Search Mechanism.
<Html>
<Head>
<Title> be cautious with the closure in the loop </title>
</Head>
<Body>
<Ul id = "list">
<Li> 1st records </li>
<Li> 2nd records </li>
<Li> 3rd records </li>
<Li> 4th records </li>
<Li> 5th records </li>
<Li> 6th records </li>
</Ul>
<Script type = "text/javascript">
Var list_obj = document. getElementById ("list"). getElementsByTagName ("li"); // obtain the array of all li objects in the list
For (var I = 0; I <= list_obj.length; I ++ ){
List_obj [I]. onmousemove = function (){
This. style. backgroundColor = "# eee ";
Document. title = I
};
List_obj [I]. onmouseout = function (){
This. style. backgroundColor = "# fff ";
}
}
</Script>
</Body>
</Html> copy the code
Why is the above Code changed to the following?
<Html>
<Head>
<Title> be cautious with the closure in the loop </title>
</Head>
<Body>
<Ul id = "list">
<Li> 1st records </li>
<Li> 2nd records </li>
<Li> 3rd records </li>
<Li> 4th records </li>
<Li> 5th records </li>
<Li> 6th records </li>
</Ul>
<Script type = "text/javascript">
Var list_obj = document. getElementById ("list"). getElementsByTagName ("li"); // obtain the array of all li objects in the list
For (var I = 0; I <= list_obj.length; I ++ ){
(Function (I ){
List_obj [I]. onmousemove = function (){
This. style. backgroundColor = "# eee ";
Document. title = I
};
List_obj [I]. onmouseout = function (){
This. style. backgroundColor = "# fff ";
}
}) (I );
}
</Script>
</Body>
</Html> copy the code
Article Reprinted from: http://www.cnblogs.com/kaima/archive/2009/03/07/advanced_javascript_concept.html