您的位置:首页 > Web前端 > JavaScript

JS闭包导致循环给按钮添加事件时总是执行最后一个

2015-02-05 17:17 531 查看
今天再做需求时有一个功能是这样的,就是有不定个的按钮,且点击按钮时都需要执行一个方法(参数不一样)

那么我很自然的就想到了,循环给每个按钮添加事件和参数就好了,由于不方便上传系统代码,下面以一个简单例子来说明.

<pre name="code" class="html"><html>
<body>
<ul id="list">
<li>按钮1</li>
<li>按钮2</li>
<li>按钮3</li>
<li>按钮4</li>
<li>按钮5</li>
</ul>
</body>
</html>



比如现在要实现这么一个功能,在页面上点击上面的按钮1到按钮5时分别alert出1,2,3,4,5.

那么很多人自然想到如下这么做:

加入如下脚本代码:

<script>
var list_obj = document.getElementsByTagName('li');
for (var i = 0; i <= list_obj.length; i++) {
list_obj[i].onclick = function() {
alert(i);
}
}
</script>


运行后,奇怪的发现无论点击那个li标签,alert出的都是最后一个的内容,5

下面做下分析:因为在for循环里面指定给list_obj[i].onclick的事件处理程序,也就是onclick那个匿名函数是在for循环执行完成后(用户单击链接时)才被调用的。而调用时,需要对变量i求值,解析程序首先会在事件处理程序内部查找,但i没有定义。然后,又到方法外部去查找,此时有定义,但i的值是4(只有i大于4才会停止执行for循环)。因此,就会取得该值——这正是闭包(匿名函数)要使用其外部作用域中变量的结果。而且,这也是由于匿名函数本身无法传递参数(故而无法维护自己的作用域)造成的。

那现在原因是知道了,如何来避免这种情况呢?

既然已经知道函数调用外部变量的时候就构成了一个闭包,里面的变量会受到别的地方的影响,那么我们

现在要做的就是,构建一个只有自己本身才可访问的闭包,保存只供本身使用的变量

构建一个闭包很简单,代码如下:

方式一:

var list_obj = document.getElementsByTagName('li');  
for (var i = 0; i <= list_obj.length; i++) {
<span style="white-space:pre">	</span>list_obj[i].onclick = (function(i){ // outer function
<span style="white-space:pre">			</span>return function(){ //inner function
<span style="white-space:pre">				</span>alert(i);
<span style="white-space:pre">			</span>};
<span style="white-space:pre">	</span>})(i);  
}*


方式二:

var list_obj = document.getElementsByTagName('li');
for (var i = 0; i <= list_obj.length; i++) {

(function(i){
//var p = i
list_obj[i].onclick = function() {
alert(i);
}
})(i);
}


现在再运行就能得到我们想要的效果了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: