代码改变世界

关于闭包一个常见的错误

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