JS 循环绑定多个元素的点击事件时出现的闭包问题与解决方案

本文讲述了在JavaScript中循环绑定多个a标签点击事件时遇到的闭包问题,导致页面加载时所有事件自动触发。通过分析,发现使用闭包可能是问题的根源。作者提供了测试代码和修改建议,提出使用$('..').each()来避免闭包问题,从而解决该问题。

      昨天在循环绑定多个a标签的点击事件时出现了不少问题,首先是 js 的典型闭包问题,这个还好以前也遇到过,于是很快解决了,但是在为多个a标签绑定点击事件成功之后,本来以为就大功告成了,结果居然是在页面加载时就自动全部a标签的点击事件自动触发了,很纳闷!!!至今还是没搞明白。测试后发现貌似是使用了闭包时才会导致此问题的发生,以下是自己写的一段建议的测试代码(仅为了说明问题而已,所以较为简陋!):

<html>
	<body>
	  <input type="text" value="请点击下列的a标签" readonly="readonly"><br/>
	  <a href="javascript:void(0)" class="testA">1</a><br/>
	  <a href="javascript:void(0)" class="testA">2</a><br/>
	  <a href="javascript:void(0)" class="testA">3</a><br/>
	  <a href="javascript:void(0)" class="testA">4</a><br/>
	  <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.6.4/jquery.min.js"></script>
	</body>
</html>
<script type="text/javascript">
   for(var i=0;i<$('.testA').length;i++){
      $('.testA')[i].onclick = (function(index){
	     alert("测试:"+index);
	  })(i);
   }
</script>
上述代码虽然解决了JS的闭包问题(将 i 变量传递给了 index 变量,使得 onclick 内部可以使用外部的 i 变量),但是导致点击事件自动触发,百度之后也没解决;后来想到一个办法即利用a标签的属性来传递值,当你要给绑定的多个a标签循环赋值一个数组时可以考虑这种方法,以下是js代码:

<script type="text/javascript">
   var content = ['a','b','c','d'];
   for(var i=0;i<$('.testA').length;i++){
      $('.testA')[i].name = content[i];//给name属性赋值
      $('.testA')[i].onclick = function(){
	     return handle(this);//这里不使用闭包但要获取content[i]的值可以通过上面设置的属性获取。
	  };
   }
   
   function handle(a){
      alert($(a).attr('name'));
	  /* 相关处理逻辑 */
   }
</script>
虽然问题解决了,但是闭包应该也是可以的,于是百度后发现一种新的写法,如下就不会产生自动触发点击事件的诡异问题了,真的是我写搓了,正确示范如下:

   for(var i=0;i<$('.testA').length;i++){
	   (function(i){
		   $('.testA')[i].onclick = function() {
			  alert("测试闭包:"+i);
		   };
	   })(i);
   }
后来还发现一个更溜的东西,直接解决了js的闭包问题,即使用关键字 let 定义变量,解释如下:


于是可以将上述代码改写如下:

   for(var i=0;i<$('.testA').length;i++){
      let index = i;
      $('.testA')[i].onclick = function(){
	     alert("测试:"+index);
       };
   }
普通写法是会导致 js 闭包问题的,如下:

   for(var i=0;i<$('.testA').length;i++){
          $('.testA')[i].onclick = function(){
	      alert("测试:"+i);//==$('.testA').length
	  };
   }

执行结果都是同个值即循环结束条件 i 的值


忽然发现使用 $('..').each() 来循环是可以避开闭包问题的:

   $('.testA').each(function(i,v){
          $(this).bind('click',function(){
	       alert("测试:"+i);
	  });
   });

好了,以上就是全部总结了!
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值