初學者經常碰到的,即獲取HTML元素集合,迴圈給元素添加事件。在事件響應函數中(event handler)獲取對應的索引。但每次獲取的都是最後一次迴圈的索引。原因是初學者並未理解JavaScript的閉包特性。 1. <!DOCTYPE HTML> 2. <html> 3. <head> 4. < ...
初學者經常碰到的,即獲取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. }