关于闭包一个常见的错误
2012-10-12 09:50 youxin 阅读(428) 评论(0) 编辑 收藏 举报看下面的一段代码才,从buttons添加不同的click事件:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <script type="text/javascript"> function func() { var bts=document.getElementsByTagName("input"); console.log(bts); var values=['text1','text2','text3']; for(var i=0;i<bts.length;i++) { (function(){ bts[i].onclick=function(){ alert(values[i]); } })(); } } window.onload=func; </script> </head> <body> <input type="button" value="button1" /> <input type="button" value="button2" /> <input type="button" value="button3" /> </body> </html>
我们虽然已经用匿名函数把循环内的代码执行了起来,但是运行时点击button都会显示undefined。我们可以加上这样的语句看到底怎么回事:
在alert(values[i]); 加上console.log(i);
因为我们的执行函数function(){ }里面的函数alert用到了i变量;
而我们的i变量有没有指定到一个特定的values[ ]上面。应该这么改:
for(var i=0;i<bts.length;i++) { var value=values[i]; (function(){ bts[i].onclick=function(){ alert(value); } })(); }
var value=values[i]; 是关键,我们用了一个变量来记录自执行的匿名函数的作用域内的值。
很多情况下循环内添加事件不能成功原因两个
1.如果出现结果显示的总是arr.length+1的值,说明我们没有使用自执行的匿名函数来运行
2.没有使用变量记住该作用域的(凡是用到i)值。
function addClickListener() { var countryItems=document.getElementsByClassName("country-item"); //console.log(countryItems); var countryLatLngArr= [ [36.83347,118.288422], //toqi [31.86502,117.30257], //tochu() [34.356475,108.583374], //toqin() [39.981329,116.383667],//toyan() [36.617181,114.428101],//tozhao [34.761923,114.307251],//towei [34.389913,113.712616] //tohan() ]; for(var i=0;i<countryItems.length;i++) { (function(){ console.log(countryLatLngArr); console.log(i); var temp=i; countryItems[i].getElementsByTagName("td")[0].onclick=function(){ /* map.panTo(new google.maps.LatLng(countryLatLngArr[i][0],countryLatLngArr[i][0])); 报错Uncaught TypeError: Cannot read property '0' of undefined */ map.panTo(new google.maps.LatLng(countryLatLngArr[temp][0],countryLatLngArr[temp][1])); //要不要加上setCenter(); } })(); } }
最开始用的是
map.panTo(new google.maps.LatLng(countryLatLngArr[i][0],countryLatLngArr[i][0]),总是报错:
Cannot read property '0' of undefined;调试时
console.log(countryLatLngArr);输出是对的啊!为什么报错是undefined?
panTo()函数里用到了i,但是此时i=arr.length;所以为undefined。