理解JavaScript闭包

代码
   
     
< ul >
< li > 1111 < / li>
< li > 2222 < / li>
< li > 3333 < / li>
< / ul>
< script >
var a = document.getElementsByTagName( ' li ' );
for ( var i = 0 ,l = a.length;i < l;i ++ ){
a[i].onclick
= function (){
alert(i)
}
}
< / script>

一个最经典的例子,上面的代码无论点击哪个结果都为最后的值,因为click事件接收的函数形成了一个闭包,闭包里的i只是对外部函数中变量i的引用,当fn执行完毕时变量i是循环得出的最后的值,闭包内的变量i也就是这个值了,所以不会依次弹出1,2.3.

至于解决的方法:

1)为遍历的每个元素添加自定义属性用来保存当前的索引值.

  
    
function fn() {
var a = document.getElementsByTagName( "li   " );
for ( var i = 0 ; i < a.length; i ++ ) {
a[i].i
= i;
a[i].onclick
= function () {
alert(
this .i);
}
}
}

 

2)将当前索引值保存到匿名函数自身.

  
    
function fn() {
var a = document.getElementsByTagName( " li " );
for ( var i = 0 ; i < a.length; i ++ ) {
(a[i].onclick
= function () {
alert(arguments.callee.i);
}).i
= i;
}
}

 

3)加一层闭包,将当前索引值以函数参数形式传递到内部函数.

  
    
function fn() {
var a = document.getElementsByTagName( " li " );
for ( var i = 0 ; i < a.length; i ++ ) {
(
function (arg){
a[i].onclick
= function () {
alert(arg);
};
})(i);
// 调用时参数
}
}

 

4)加一层闭包,将当前索引值以变量形式传递到内不函数.

代码
   
     
function fn() {
var a = document.getElementsByTagName( " li " );
for ( var i = 0 ; i < a.length; i ++ ) {
(
function () {
var index = i; // 调用时局部变量
a[i].onclick = function () {
alert(index);
}
})();
}
}

 

5)加一层闭包,返回一个函数作为响应事件.

代码
   
     
function fn() {
var a = document.getElementsByTagName( " li " );
for ( var i = 0 ; i < a.length; i ++ ) {
a[i].onclick
= function (arg) {
return function () { // 返回一个函数
alert(arg);
}
}(i);
}
}

 

6)利用Function对象,需要注意的是Function构造函数是在脚本运行时创建函数并将参数用作新函数的参数,所以相对前几种方法执行效率较低.

  
    
function fn() {
var a = document.getElementsByTagName( " li " );
for ( var i = 0 ; i < a.length; i ++ ) {
a[i].onclick
= Function( ' alert( ' + i + ' ) ' )
}
}

 

7)利用Function对象实例来产生闭包.

  
    
function fn() {
var a = document.getElementsByTagName( " li " );
for ( var i = 0 ; i < a.length; i ++ ) {
a[i].onclick
= new Function( ' alert('   + i +'   )'   ); // new一次就产生一个函数实例
}
}

你可能感兴趣的:(JavaScript)