初学者经常碰到的,即获取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.  }