js高级_110、循环遍历监听

js循环绑定事件

在编写JS代码的时候,我们经常会遇到要对一系列元素进行事件绑定的情况,然后就会理所当然的开一个for循环,对元素的事件进行赋值等操作,最后运行的效果却不是希望有的样子,事件的响应只能和最后一个元素一样。
html元:希望给每个按钮都绑定单击事件,输出他们是第几个按钮

<body>
		    <button>测试1</button>
		    <button>测试2</button>
		    <button>测试3</button>
		    
	</body>

.length不是一直在里面,而是每一次循环都要计算统计这个伪数组的length是多少,效率比较慢,
image

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是全局的
		
	}
posted @ 2022-03-14 16:24  青仙  阅读(298)  评论(0编辑  收藏  举报