初学者经常碰到的,即获取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. 5-API 网关 kong 实战

    原文:https://cloud.tencent.com/developer/article/1477672 1. 什么是Kong? 目前互联网后台架构一般是采用微服务,或者类似微服务的形式,应用的请 ...

  2. JAVA笔记 -- this关键字

    this关键字 一. 基本作用 在当前方法内部,获得当前对象的引用.在引用中,调用方法不必使用this.method()这样的形式来说明,因为编译器会自动的添加. 必要情况: 为了将对象本身返回 ja ...

  3. 【转载】不可不知的 Android strings.xml 那些事

    相信 strings.xml 已经是大家在 Android 开发中最熟悉的文件之一了,但其实它也有很多需要注意的地方和一些小技巧,知道了这些可以让你的 Android 应用更加规范易用,大家来看看吧. ...

  4. /cygdrive/c/MinGW/bin/autoconf-2.68: line 501: /mingw/bin/autom4te-2.68: No such file or directory

    出现如下错误 编译openssh的时候 # autoconf /cygdrive/c/MinGW/bin/autoconf-2.68: line 501: /mingw/bin/autom4te-2. ...

  5. [20190522]DISABLE TABLE LOCK.txt

    [20190522]DISABLE TABLE LOCK.txt --//如果禁止table lock时,一些ddl操作会被禁止.但是我有点吃惊的是增加字段不受限制.--//通过测试说明问题. 1.环 ...

  6. zsh: command not found: 解决方法

    问题原有:mac中安装了my zsh [https://www.cnblogs.com/dadonggg/p/11027454.html] ,但是造成了在使用vscode的时候,提示”zsh: com ...

  7. 解决汉化pycharme之后设置打不开的问题

    首先进入安装pycharme目录下lib目录下,将汉化包移出去,只留下英文包 然后打开pycharme即可打开设置 在你改完设置之后,可以再将汉化包放进来 英文包:https://pan.baidu. ...

  8. Centos 7 自动安装系统-pxe

    一.简介 PXE(Pre-boot Execution Environment,预启动执行环境)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持工作站通过网络从远端服 ...

  9. HAproxy四层TCP负载均衡配置及测试

    --------------------------------------------------centos 7 处理--------------------------------------- ...

  10. BASIC合集

    握手包 给你握手包,flag是Flag_is_here这个AP的密码,自己看着办吧. 提交格式:flag{WIFI密码} 破解wifi密码 丢到kali,用aircrack-ng kali有一个包含常 ...