js高级_110、循环遍历监听
js循环绑定事件
在编写JS代码的时候,我们经常会遇到要对一系列元素进行事件绑定的情况,然后就会理所当然的开一个for循环,对元素的事件进行赋值等操作,最后运行的效果却不是希望有的样子,事件的响应只能和最后一个元素一样。
html元:希望给每个按钮都绑定单击事件,输出他们是第几个按钮
<body>
<button>测试1</button>
<button>测试2</button>
<button>测试3</button>
</body>
.length不是一直在里面,而是每一次循环都要计算统计这个伪数组的length是多少,效率比较慢,
var btns=document.getElementsByTagName("button");//返回的是一个元素对象的伪数组
//这样只需要计算一次。
//遍历加监听
for (var i=0,btnsLength=btns.length ;i<btnsLength;i++) {
var btn=btns[i];
btn.onclick=function(){
alert("第"+(i+1)+"个");
}
}
如果是上面这样写的话,不管点击那个按钮,都是输出“第4个”,因为js的函数是触发时调用的,绑定事件的时候i并没有被传入执行函数里。这里的onclick函数中的变量i指向的内存地址,在循环结束后变成了3,所以所有的btn在点击后都输出3。上面这个方法执行后,会发现遍历数组后,监听到的事件,索引值始终等于遍历结束之后的值。错误原因:JS引擎的解析机制是,执行的时候将for循环中代码执行,这个时候i变成最后的值,当发生onclick事件时,会找到运算之后的i,因此绑定的事件是最后的。因为for循环已经执行完了。全局变量i的值已经是3了,而执行for循环中代码时,并不会调用onclick函数,等你单击才调用,才传i给函数。
解决方法1,给每个button元素添加index属性,这样每次点击触发时用自己的属性输出。
//利用index属性
for (var i=0,btnsLength=btns.length ;i<btnsLength;i++) {
var btn=btns[i];
btn.index=i;
btn.onclick=function(){
alert("第"+(this.index+1)+"个");
}
}
解决方法2,利用闭包
//利用闭包
for (var i=0,btnsLength=btns.length ;i<btnsLength;i++) {
(function(i){//这里的i是函数内部自己的。
var btn=btns[i];
btn.onclick=function(){
alert("第"+(i+1)+"个");
}
})( i);//这里的i是全局的
}