2010-06-13 104 views
0

我想让每个数字都显示为可点击。 “1” 应alert() 80, “2” 应该产生60等MooTools/JavaScript可变范围

然而,当alert(adjust)被调用时,它仅示出了0,而不是正确的数字。但是,如果注释掉alert(adjust)未注释,它会在页面加载时生成正确的数字,但不会在单击时生成。

我想知道为什么addEvents内的代码无法访问先前定义的变量adjust

<html> 
<head> 
<script type="text/javascript" charset="utf-8" src="mootools.js"></script> 
<script type="text/javascript" charset="utf-8"> 
    window.addEvent('domready', function() { 

      var id_numbers = [1,2,3,4,5]; 

      for(var i = 0; i<id_numbers.length; i++) { 
       var adjust = (20 * (5 - id_numbers[i])); 
       // alert(adjust); 
       $('i_' + id_numbers[i]).addEvents({ 
        'click': function() { 
         alert(adjust); 
        } 
       }); 
      } 

    }); 
</script> 
</head> 
<body> 

<div id="i_1">1</div> 
<div id="i_2">2</div> 
<div id="i_3">3</div> 
<div id="i_4">4</div> 
<div id="i_5">5</div> 

</body> 
</html> 

谢谢。

+0

这是一个常见的问题 - 请参阅相关的问题和答案http://stackoverflow.com/questions/tagged/javascript +瓶盖+循环。 – Anurag 2010-06-13 02:33:50

回答

3

您在for循环中有a very common closure problem

变量封闭在一个封闭共享同一个单一的环境中,因此受到click回调被调用时,该for循环就会自生自灭,而adjust变量将指向左侧的最后的值就被分配。

你可以用更倒闭解决这个问题,使用函数工厂:

function makeClickHandler(adjust) { 
    return function() { 
     alert(adjust); 
    }; 
} 

// ... 

for(var i = 0; i<id_numbers.length; i++) { 
    var adjust = (20 * (5 - id_numbers[i])); 

    $('i_' + id_numbers[i]).addEvents({ 
     'click': makeClickHandler(adjust) 
    }); 
} 

这可以说是相当棘手的话题,如果你不熟悉闭包是如何工作的。您可以检查出以下Mozilla的文章作一简要介绍: