JS闭包导致循环给按钮添加事件时总是执行最后一个
2015-02-05 17:17
531 查看
今天再做需求时有一个功能是这样的,就是有不定个的按钮,且点击按钮时都需要执行一个方法(参数不一样)
那么我很自然的就想到了,循环给每个按钮添加事件和参数就好了,由于不方便上传系统代码,下面以一个简单例子来说明.
比如现在要实现这么一个功能,在页面上点击上面的按钮1到按钮5时分别alert出1,2,3,4,5.
那么很多人自然想到如下这么做:
加入如下脚本代码:
运行后,奇怪的发现无论点击那个li标签,alert出的都是最后一个的内容,5
下面做下分析:因为在for循环里面指定给list_obj[i].onclick的事件处理程序,也就是onclick那个匿名函数是在for循环执行完成后(用户单击链接时)才被调用的。而调用时,需要对变量i求值,解析程序首先会在事件处理程序内部查找,但i没有定义。然后,又到方法外部去查找,此时有定义,但i的值是4(只有i大于4才会停止执行for循环)。因此,就会取得该值——这正是闭包(匿名函数)要使用其外部作用域中变量的结果。而且,这也是由于匿名函数本身无法传递参数(故而无法维护自己的作用域)造成的。
那现在原因是知道了,如何来避免这种情况呢?
既然已经知道函数调用外部变量的时候就构成了一个闭包,里面的变量会受到别的地方的影响,那么我们
现在要做的就是,构建一个只有自己本身才可访问的闭包,保存只供本身使用的变量
构建一个闭包很简单,代码如下:
方式一:
方式二:
现在再运行就能得到我们想要的效果了。
那么我很自然的就想到了,循环给每个按钮添加事件和参数就好了,由于不方便上传系统代码,下面以一个简单例子来说明.
<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); }
现在再运行就能得到我们想要的效果了。
相关文章推荐
- JS闭包导致循环给按钮添加事件时总是执行最后一个
- 循环按钮添加事件总是执行最后一个的解决办法汇总
- JS循环给li添加单击事件时总是弹出最后一个i值
- JS 循环li添加点击事件 (闭包的应用)
- js实现为a标签添加事件的方法(使用闭包循环)
- javascript循环添加事件,总是获取最后一个值
- 从循环添加事件谈起对JS闭包的理解
- JS 循环li添加点击事件 (闭包的应用)
- js循环添加onClick事件--js的闭包
- VBS一键配置VOIP脚本(其中包括VBS操作JS网页中的按钮事件--直接执行确认按钮中的脚本代码)
- Js定时执行函数方法setTimeout,clearTimeout用法及按钮addEventListener,attachEvent侦听事件
- 闭包实现循环事件添加
- 深入理解JavaScript的闭包特性如何给循环中的对象添加事件(转)
- js 利用闭包循环给li绑定参数不同的点击事件
- 用JS给浏览器的关闭按钮添加事件
- JS实现按钮清除单击事件,或单击事件执行一次
- for循环绑定监听事件索引值总是最后一个
- radioButton事件重载,用于多选择按钮的情形,不用每一个radiobutton都添加选中执行事件
- 深入理解JavaScript的闭包特性 如何给循环中的对象添加事件
- js,在循环中添加事件,输出循环数 i 的值,i++与++i的问题