日期:2014-05-16  浏览次数:20410 次

Javascript闭包演示

有个网友问了个问题,如下的html,为什么点击所有的段落p输出都是5,而不是alert出对应的0,1,2,3,4。

<!DOCTYPE HTML>
< html >
< head >
< meta charset = "utf-8" />
< title >闭包演示</ title >
< style type = "text/css" >
???? p {background:gold;}
</ style >
< script type = "text/javascript" >
function init() {???
???? var pAry = document.getElementsByTagName_r("p");???
???? for( var i=0; i< pAry.length ; i++ ) {???
????????? pAry[i] .onclick = function () {???
????????? alert(i);???
???? }
?? }
}
</script>
</ head >
< body onload = "init();" >
< p >产品 0</ p >
< p >产品 1</ p >
< p >产品 2</ p >
< p >产品 3</ p >
< p >产品 4</ p >
</ body >
</ html >

以上场景是初学者经常碰到的。即获取HTML元素集合,循环给元素添加事件。在事件响应函数中(event handler)获取对应的索引。但每次获取的都是最后一次循环的索引。

原因是初学者并未理解JavaScript的闭包特性。通过element.onclick=function(){alert(i);}方式给元 素添加点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。


了解了原因,摸索出了很多解决办法(纯粹是兴趣)。最先想到的前两种

1、将变量 i 保存给在每个段落对象(p)上

unction init1() {
?? var pAry = document.getElementsByTagName_r( "p" );
?? for ( var i=0; i<pAry.length; i++ ) {
????? pAry[i].i = i;
????? pAry[i].onclick = function () {
???????? alert( this .i);
????? }
?? }
}

2、将变量 i 保存在匿名函数自身

function init2() {
?? var pAry = document.getElementsByTagName_r(