什么是闭包?以下代码点击<p> 会输出什么?为什么?能大概说明白的话继续问能想出几种解决办法。
==========
出错:获取HTML元素集合,循环给元素添加事件。在事件响应函数中(event handler)获取对应的索引。但每次获取的都是最后一次循环的索引。
出错原因:初学者并未理解JavaScript的闭包特性。通过element.onclick=function(){alert(i);}方式给元素添加点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。
解决方法:见html代码注释部分
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8" /> <title>闭包演示</title> <style type="text/css"> p {background:gold;} </style> <script type="text/javascript"> /* 网上的七种方法 //将变量 i 保存给在每个段落对象上 function init() { var pAry = document.getElementsByTagName("p"); for( var i=0; i<pAry.length; i++ ) { pAry[i].i=i; pAry[i].onclick = function() { alert(this.i); } } } //将变量i保存在匿名函数自身 function init(){ var pAry=document.getElementsByTagName("p"); for (var i = 0; i <pAry.length; i++) { (pAry[i].onclick=function(){ alert(arguments.callee.i) }).i=i; }; } //加一层闭包,i以函数参数形式传递给内层函数 function init(){ var pAry=document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { (function(arg){ pAry[i].onclick=function(){ alert(arg); }; })(i);//调用时参数 }; } //加一层闭包,i 以局部变量形式传递给内层函数 function init(){ var pAry=document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { (function(){ var temp=i;//调用时局部变量 pAry[i].onclick=function(){ alert(temp); } })(); }; } //加一层闭包,返回一个函数作为响应事件 function init(){ var pAry=document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { pAry[i].onclick=function(arg){ return function(){ alert(arg); } }(i); }; } function init(){ var pAry=document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { pAry[i].onclick=new Function("alert("+i+");");//new一次就产生一个函数实例 }; } function init(){ var pAry=document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { pAry[i].onclick=Function("alert("+i+");"); }; } */ function init() { var pAry = document.getElementsByTagName("p"); for( var i=0; i<pAry.length; i++ ) { pAry[i].onclick = function() { alert(i); } } } </script> </head> <body onload="init();"> <p>产品 0</p> <p>产品 1</p> <p>产品 2</p> <p>产品 3</p> <p>产品 4</p> </body> </html>