An uncommon closure trap:
VaR Test1 = {Name: ' Cson ' };
VaR Name = ' Noname ' ;
With (Test1 ){
Function Setname (){
Name = ' Xiaoc ' ;
}
Setname ();
}
Alert (test1.name );
Alert (name );
We often see a description similar to this in the document: With opens the object closure, and sets the attribute and method in the object closure to add attributes and methods for the object. According to this understanding, the above results should be: 'xiaoc 'and 'noname '.
However, the experimental results are 'cson' and 'xiaoc '. (Ie chrome) 'xiaoc 'and 'noname' (Firefox ).
Analysis:
In fact, it is not perfect to say that setting attributes and methods in the with object closure is equal to adding attributes and methods to the object. The exception is that when the closure of nested functions in the object closure is, in this case, apart from Firefox's approval of the above sentence, ie and chrome will use another method for processing.
We know that JavaScript has two runtime cycles: the parsing cycle and the execution cycle. When processing the above process, Firefox and IE chrome adopt different processing methods:
Firefox considers:The declaration in the object closure and the object closure itself (that is, it is treated as the property of test1). Therefore, setname is created as a method property of test1, so the name processed in it is the name attribute of test1.
However, ie and chrome think:The declaration in the object closure should not work with the object closure. In the parsing cycle of JS, since with has not yet worked, they resolve the setname declaration to the global closure domain, and then make setname and with the "same level ", therefore, the name set in setname becomes the global name variable.
Solution:
To sum up, we only need to change the function declaration in the object closure into a value assignment, so that IE and chrome can avoid parsing setname in the global closure during the JS parsing cycle.
FunctionSetname (){
Name= 'Xiaoc';
}
Change
VaRSetname=Function(){
Name= 'Xiaoc';
}
In this way, the "Declaration" is changed to "value assignment", and all browser engines process the function in the execution cycle of Js.
After modification, the output of Firefox ie Chrome is 'xiaoc 'and 'noname'
An uncommon technique about closures:
You should be familiar with the classic issue of this closure:
< Div ID = "A0" > A0 </ Div >
< Div ID = "A1" > A1 </ Div >
< Div ID = "A2" > A2 </ Div >
< Div >
Function Test2 (){
For ( VaR I = 0 ; I < 3 ; I ++ ){
Document. getelementbyid ( ' A ' + I). onclick = Function () {Alert (I );}
}
}
Test2 ();
The result is that after the three elements of A0 A1 A2 are clicked, the alert value is 3, because the closure makes them use the same I value.
The classic solution is:
Function Test2 (){
For ( VaR I = 0 ; I < 3 ; I ++ ){
( Function (){
VaR J = I;
Document. getelementbyid ( ' A ' + I). onclick = Function () {Alert (j );}
})();
}
}
Test2 ();
However, this poses a problem. Only external DOM elements do not release the reference, and the closure causes the variable objects on the entire scope chain to be stored in the memory, resulting in performance loss, is there a better way to solve this problem without using closures?
A better method is as follows:
Function Test2 (){
For ( VaR I = 0 ; I < 3 ; I ++ ){
(Document. getelementbyid ( ' A ' + I). onclick = Function () {Alert (arguments. callee. J);}). j = I;
}
}
Test2 ();
It cleverly solves the problem by setting custom attributes for the function without using closures.
Reference books: javascript advancedProgramDESIGN: javascript language essence and programming practices
Welcome to reprint, please indicate the source: http://www.cnblogs.com/Cson/archive/2011/03/31/2001631.html