js循环绑定事件的问题

在编写js代码时,我们可能需要给一组对象绑定同一个事件,当我们兴高采烈地用for循环绑定完事件后以为往事大吉的时候,会发生一些很神奇的事情,下面先举个例子:

1
2
3
4
//用for循环打印出i,每次叠加1
for(var i=0;i<4;i++){
console.log(i)
}

打印出来你会发现很正常:0,1,2,3,

但是请看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var oLis = document.getElementsByTagName('li');
for (var i = 1;i<6;i++){
oLis[i].onclick = function(){
alert(i)
}
}
</script>
</body>

这里的结果就比较诡异了,无一例外点击弹出的结果都是6,其实是因为我们的函数时动态绑定的,在我们页面加载完后js已经把for循环执行完了,此时i等于6,所以当我们触发事件后得到的都是同一结果。


那么,有什么办法可以解决吗?答案是有,而且不止一种!

即时函数

我们可以通过在外层用一个即时函数包裹住内部函数,这样循环一次就会生成一个作用域,参数由即时函数的尾部传入,如下:

1
2
3
4
5
6
7
8
9
10
11
12
<script>
var oLis = document.getElementsByTagName('li');
for (var i = 1;i<6;i++){
(function(i){
oLis[i].onclick = function(){
alert(i)
}
})(i)
}
</script>

运行以上代码,你会发现已经可以实现功能了^_^!

给元素绑定属性

第二种方法同样简单,只需把循环的i赋值给元素作为它的私有属性就ok了,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
<script>
var oLis = document.getElementsByTagName('li');
for (var i = 1;i<6;i++){
oLis[i].i = i;
oLis[i].onclick = function(){
alert(this.i)
}
})(i)
}
</script>

这样写同样可以实现循环绑定动态事件,此外还有解决问题的其他方法,大家可以自行探索,关于js实现循环绑定动态事件的分享就到这里了!