先看一下代码:
01 |
<ul> |
02 |
<li>1111</li> |
03 |
<li>2222</li> |
04 |
<li>3333</li> |
05 |
</ul> |
06 |
<script> |
07 |
var a=document.getElementsByTagName( 'li' ); |
08 |
for ( var i=0,l=a.length;i<l;i++){ |
09 |
a[i].onclick= function (){ |
10 |
alert(i) |
11 |
} |
12 |
} |
13 |
</script> |
一个最经典的例子,上面的代码无论点击哪个结果都为最后的值,因为click事件接收的函数形成了一个闭包,闭包里的i只是对外部函数中变量i的引用,当fn执行完毕时变量i是循环得出的最后的值,闭包内的变量i也就是这个值了,所以不会依次弹出1,2,3。
至于解决的方法:
1 |
function fn() { |
2 |
var a = document.getElementsByTagName( "li " ); |
3 |
for ( var i=0; i<a.length; i++ ) { |
4 |
a[i].i = i; |
5 |
a[i].onclick = function () { |
6 |
alert( this .i); |
7 |
} |
8 |
} |
9 |
} |
2. 将当前索引值保存到匿名函数自身。
1 |
function fn() { |
2 |
var a = document.getElementsByTagName( "li" ); |
3 |
for ( var i=0; i<a.length; i++ ) { |
4 |
(a[i].onclick = function () { |
5 |
alert(arguments.callee.i); |
6 |
}).i = i; |
7 |
} |
8 |
} |
3. 加一层闭包,将当前索引值以函数参数形式传递到内部函数。
01 |
function fn() { |
02 |
var a = document.getElementsByTagName( "li" ); |
03 |
for ( var i=0; i<a.length; i++ ) { |
04 |
( function (arg){ |
05 |
a[i].onclick = function () { |
06 |
alert(arg); |
07 |
}; |
08 |
})(i); //调用时参数 |
09 |
} |
10 |
} |
4. 加一层闭包,将当前索引值以变量形式传递到内不函数。
01 |
function fn() { |
02 |
var a= document.getElementsByTagName( "li" ); |
03 |
for ( var i=0; i<a.length; i++ ) { |
04 |
( function () { |
05 |
var index = i; //调用时局部变量 |
06 |
a[i].onclick = function () { |
07 |
alert(index); |
08 |
} |
09 |
})(); |
10 |
} |
11 |
} |
5. 加一层闭包,返回一个函数作为响应事件。
01 |
function fn() { |
02 |
var a = document.getElementsByTagName( "li" ); |
03 |
for ( var i=0; i<a.length; i++ ) { |
04 |
a[i].onclick = function (arg) { |
05 |
return function () { //返回一个函数 |
06 |
alert(arg); |
07 |
} |
08 |
}(i); |
09 |
} |
10 |
} |
6. 利用Function对象,需要注意的是Function构造函数是在脚本运行时创建函数并将参数用作新函数的参数,所以相对前几种方法执行效率较低。
1 |
function fn() { |
2 |
var a = document.getElementsByTagName( "li" ); |
3 |
for ( var i=0; i<a.length; i++ ) { |
4 |
a[i].onclick = Function( 'alert(' +i+ ')' ) |
5 |
} |
6 |
} |
7. 利用Function对象实例来产生闭包。
1 |
function fn() { |
2 |
var a= document.getElementsByTagName( "li" ); |
3 |
for ( var i=0; i"a.length; i++ ) { |
4 |
a[i].onclick = new Function( 'alert(' +i+ ' )' ); //new一次就产生一个函数实例 |
5 |
} |
6 |
} |