加入如下脚本代码:

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

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

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

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

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

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

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

方式一:

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

方式二:

  1. var list_obj = document.getElementsByTagName('li');
  2. for (var i = 0; i <= list_obj.length; i++) {
  3. (function(i){
  4. //var p = i
  5. list_obj[i].onclick = function() {
  6. alert(i);
  7. }
  8. })(i);
  9. }

JS闭包导致循环给按钮添加事件时总是执行最后一个的更多相关文章

  1. js用for循环为对象添加事件并传递参数

    var objArr = getObjArr(id);   for(var i=0; i<objArr.length; i++){    var param=objArr.param    ad ...

  2. Unity3D的按钮添加事件有三种方式

    为Unity3D的按钮添加事件有三种方式,假设我们场景中有一个Canvas对象,Canvas对象中有一个Button对象. 方式一: 创建脚本ClickObject.cs,然后将脚本添加到Canvas ...

  3. vuejs 添加事件时出现TypeError: n.apply is not a function

    vuejs项目中给表单元素添加事件时出现了TypeError: n.apply is not a function的错误,后来发现错误原因时处理事件的函数名和data中定义的变量名相同 当给事件添加处 ...

  4. GUI编程笔记(java)06:GUI窗体添加按钮并对按钮添加事件案例

    1.需求:把按钮添加到窗体,并对按钮添加一个点击事件. 步骤: (1)创建窗体对象(2)创建按钮对象(3)把按钮添加到窗体(4)窗体显示 2.编写程序思路: 窗体布局:窗体中组件的排列方式  布局分类 ...

  5. js闭包解决多个点击事件

    <script> var severalObj=window.document.getElementsByName("button"); for(var i=0;i&l ...

  6. 【转】为ListView每个Item上面的按钮添加事件

    原文网址:http://blog.csdn.net/qq435757399/article/details/8256453 1.先看下效果图:        在这里仅供测试,我把数据都写死了,根据需要 ...

  7. Js闭包与循环

    目标:点击任何一个li,提示当前点击位置 <ul> <li>第1个</li> <li>第2个</li> <li>第3个</ ...

  8. js闭包for循环总是只执行最后一个值得解决方法

    <style> li{ list-style: none;width:40px;height: 40px;text-align:center;line-height: 40px;curso ...

  9. 一百、SAP中ALV事件之十三,给ALV的自定义按钮添加事件

    一.我们查看定义的按钮,有一个名字是ZADD的自定义按钮 二.代码如下,用于判断点击了哪个按钮 三.点击测试按钮之后,会弹出一个弹窗 完美

随机推荐

  1. Joomla 3.2.0 - 3.4.4 无限制SQL注入漏洞

    http://www.sebug.net/vuldb/ssvid-89680#0-tsina-1-18081-397232819ff9a47a7b7e80a40613cfe1 http://10.21 ...

  2. git管理maven项目实现

    1,在自己的git网新建一个项目.复制项目的地址. 2.在合适的目录  执行 git clone命令,这样就把git的本地仓库建立好了. 3,java中 ,新建maven项目, 在location这里 ...

  3. 类似input框内最右边添加图标,有清空功能

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  4. Nginx localtion匹配规则

    mark:2016年05月25日13:20:54 (存手打,拒绝转载) 一.location分为 普通location 和 正则location 只有带有 "~" 或者" ...

  5. Centos上Docker 使用dockerfile构建容器实现ssh

    这几日在学习docker.遇到的问题数一年都数不完,网上大多数都是ubuntu的,百度或者谷歌的时候心好累.写写文档来帮助使用centos的docker爱好者们. docker基本操作这里就不介绍了 ...

  6. PropertiesUtil.java

    package com.vcredit.ddcash.batch.util; import java.io.BufferedReader;import java.io.File;import java ...

  7. DS Tree 已知后序、中序 => 建树 => 求先序

    注意点: 和上一篇的DS Tree 已知先序.中序 => 建树 => 求后序差不多,注意的地方是在aftorder中找根节点的时候,是从右往左找,因此递归的时候注意参数,最好是拿纸和笔模拟 ...

  8. 使用safe-rm替代rm

    safe-rm主页: https://launchpad.net/safe-rm 一.下载safe-rm 二.解压文件,拷贝safe-rm到/usr/local/bin/目录下 三.建立软连接: #l ...

  9. Android WebView常见问题及解决方案汇总

    Android WebView常见问题解决方案汇总: 就目前而言,如何应对版本的频繁更新呢,又如何灵活多变地展示我们的界面呢,这又涉及到了web app与native app之间孰优孰劣的争论. 于是 ...

  10. CSS 伪元素&伪类

    单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素 伪元素 属性 描述 CSS :first-letter 向文本的第一个字母添加特殊样式 1 :first-line 向文本的首行添加特殊 ...