初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件。在事件响应函数中(event handler)获取对应的索引。但每次获取的都是最后一次循环的索引。原因是初学者并未理解JavaScript的闭包特性。

1. <!DOCTYPE HTML>

2.  <html>

3.  <head>

4.  <meta charset="utf-8" />

5.  <title>闭包演示</title>

6.  <style type="text/css">

7.      p {background:gold;}

8.  </style>

9.  <script type="text/javascript">

10.function init() {

11.    var pAry = document.getElementsByTagName("p");

12.    for( var i=0; i<pAry.length; i++ ) {

13.         pAry[i].onclick = function() {

14.         alert(i);

15.    }

16.  }

17.}

18.</script>

19.</head>

20.<body οnlοad="init();">

21.<p>产品 0</p>

22.<p>产品 1</p>

23.<p>产品 2</p>

24.<p>产品 3</p>

25.<p>产品 4</p>

26.</body>

27.</html>

以上场景是初学者经常碰到的。即获取HTML元素集合,循环给元素添加事件。在事件响应函数中(event handler)获取对应的索引。但每次获取的都是最后一次循环的索引。

原因是初学者并未理解JavaScript的闭包特性。通过element.οnclick=function(){alert(i);}方式给元 素添加点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。

了解了原因,下面就由几种方式可与解决:

1、将变量 i 保存给在每个段落对象(p)上

1.  function init1() {

2.    var pAry = document.getElementsByTagName("p");

3.    for( var i=0; i<pAry.length; i++ ) {

4.       pAry[i].i = i;

5.       pAry[i].onclick = function() {

6.          alert(this.i);

7.       }

8.    }

9.  }

2、将变量 i 保存在匿名函数自身

1.  function init2() {

2.    var pAry = document.getElementsByTagName("p");

3.    for( var i=0; i<pAry.length; i++ ) {

4.     (pAry[i].onclick = function() {

5.          alert(arguments.callee.i);

6.      }).i = i;

7.    }

8.  }

3、加一层闭包,i 以函数参数形式传递给内层函数

1.  function init3() {

2.    var pAry = document.getElementsByTagName("p");

3.    for( var i=0; i<pAry.length; i++ ) {

4.     (function(arg){

5.         pAry[i].onclick = function() {

6.            alert(arg);

7.         };

8.     })(i);//调用时参数

9.    }

10.}

4、加一层闭包,i 以局部变量形式传递给内层函数

1.  function init4() {

2.    var pAry = document.getElementsByTagName("p");

3.    for( var i=0; i<pAry.length; i++ ) {

4.      (function () {

5.        var temp = i;//调用时局部变量

6.        pAry[i].onclick = function() {

7.          alert(temp);

8.        }

9.      })();

10.  }

11.}

5、加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)

1.  function init5() {

2.    var pAry = document.getElementsByTagName("p");

3.    for( var i=0; i<pAry.length; i++ ) {

4.     pAry[i].onclick = function(arg) {

5.         return function() {//返回一个函数

6.         alert(arg);

7.       }

8.     }(i);

9.    }

10.}

6、用Function实现,实际上每产生一个函数实例就会产生一个闭包

1.  function init6() {

2.      var pAry = document.getElementsByTagName("p");

3.      for( var i=0; i<pAry.length; i++ ) {

4.        pAry[i].onclick = new Function("alert(" + i + ");");//new一次就产生一个函数实例

5.      }

6.  }

7、用Function实现,注意与6的区别

1.  function init7() {

2.      var pAry = document.getElementsByTagName("p");

3.      for( var i=0; i<pAry.length; i++ ) {

4.           pAry[i].onclick = Function('alert('+i+')');

5.      }

6.  }

JavaScript的闭包特性如何给循环中的对象添加事件(一)的更多相关文章

  1. 深入理解JavaScript的闭包特性如何给循环中的对象添加事件

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  2. 深入理解JavaScript的闭包特性 如何给循环中的对象添加事件(转载)

    原文参考:http://blog.csdn.net/gaoshanwudi/article/details/7355794 初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数 ...

  3. 如何给循环中的对象添加事件--深入理解JavaScript的闭包特性

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  4. 给ul中的li添加事件的多种方法

    给ul中的li添加事件的多种方法 这是一个常见,而且典型的前端面试题 <ul> <li>11111</li> <li>22222</li> ...

  5. React 函数组件中对window添加事件监听resize导致回调不能获得Hooks最新状态的问题解决思路

    React 函数组件中对window添加事件监听resize导致回调不能获得Hooks最新状态的问题解决思路 这几天在忙着把自己做的项目中的类组件转化为功能相同的函数组件,首先先贴一份该组件类组件的关 ...

  6. JavaScript的闭包特性

    闭包是一个比较抽象的概念,尤其是对js新手来说.在这里,我就我个人的理解j简单谈一下: 闭包:官方解释是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部 ...

  7. JavaScript基础&实战(4)js中的对象、函数、全局作用域和局部作用域

    文章目录 1.对象的简介 2.对象的基本操作 2.1 代码 2.2 测试结果 3.属性和属性值 3.1 代码 3.2 测试结果 4.对象的方法 4.1 代码 4.2 测试结果 5.对象字面量 5.1 ...

  8. PHP 循环中临时对象不销毁,会保存到一下循环,这是什么坑。。

    在C++中,根本存在这种问题,一个对象或结构体在循环中声明赋值了,再一次循环就自动清空.但是在PHP中这个$monthData在下一次循环却不会重新赋值,而是保留了上一次赋值的值,这样的下一次save ...

  9. JavaScript中给对象添加方法

    在JavaScript中,我们经常要给已定义的对象添加一些方法,如下:    function circle(w,h){      this.width=w;      this.height=h; ...

随机推荐

  1. 零零总总遇到过的CSS 样式

    1:添加弹出框阴影 2:禁止文本域缩放 3:直接使用CSS 完成文本内容大小写(针对英文) 4: 文本框中的占位符 5:让table每列一样高 6:不使用js 让内容换行 word-break 7:曾 ...

  2. vue-商品管理案例改进

    案例改进 vue-resource全局配置: Vue.http.options.root = 'http://vue.studyit.io/'; 全局启用 emulateJSON 选项 Vue.htt ...

  3. XAF中多对多关系 (XPO)

    In this lesson, you will learn how to set relationships between business objects. For this purpose, ...

  4. cesium-webpack 入门开发系列一初探篇(附源码下载)

    前言 cesium-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 we ...

  5. Python的lambda表达式、filter、map、reduce等函数的用法

    lambda是表达式,用于创建匿名函数,可以和filter.map.reduce配合使用.本文环境Python3.7. 一.lambda表达式 lambda 只包含一个语句,用于创建匿名函数. 语法: ...

  6. C# 运行时的关系

    简介 记录c#对象在托管堆中运行时的相互关系,如下记录了一个方法在执行时候的生命周期,当方法在之前,CLR会先执行将方法里面所有用到的局部变量.参数对应的内存地址等全部存放当前线程栈当中,并且会将所有 ...

  7. 【cf570】D. Tree Requests(dsu on tree)

    传送门 题意: 给出一个以\(1\)为根的有根树.之后有\(m\)个询问,每个询问为\(v_i,h_i\),需要回答以\(v_i\)为根的子树中,深度为\(h_i\)的那些结点所代表的字符能否构成回文 ...

  8. luoguP2163 [SHOI2007]园丁的烦恼

    安利系列博文 https://www.cnblogs.com/tyner/p/11565348.html https://www.cnblogs.com/tyner/p/11605073.html 题 ...

  9. 日志分析利器Splunk的搭建、使用、破解

    博主对splunk的了解不多,博主的使用目的是为了同步,分析日志.当初的搭建也是为了公司申请牌照需要日志服务器分析日志,顺便自己也对这方面感兴趣就买了本书看了看搭建玩的,后来检查来了博主也给他们演示了 ...

  10. 5、zabbix数据库分离

    环境: zabbix端:zabbix3.4(192.168.80.66) 数据库端:mysql5.7(192.168.80.88) 被监控端:web01(192.168.80.240) 为什么要将数据 ...