我在这个简单的Closure上做错了什么

时间:2010-01-18 09:24:35

标签: javascript javascript-events closures

它可能是睡眠剥夺,但我无法理解为什么这不起作用。我希望onclick从创建元素的for循环返回i的值并应用事件处理程序。把它放在一个闭包中,它仍然是转动迭代器的最大数量。

window.onload = function(){
  var arbitrary_amount = 100;
  var the_list = document.getElementsByTagName('ul')[0];

  for(var i = 0; i < arbitrary_amount; i++){
    var natural_index = i + 1;
    var list_item = document.createElement('li');
    var inner_link = document.createElement('a');
    inner_link.setAttribute('href', '#');
    inner_link.innerHTML = "Link "+natural_index;

    inner_link.onclick = function(){
      return function(link_num){
        alert('You clicked link '+link_num);
      }(i);
    };

    list_item.appendChild(inner_link);
    the_list.appendChild(list_item);
  }


};

5 个答案:

答案 0 :(得分:8)

你正在以错误的方式使用闭包......我不能给你一个关于实际发生的事情的大师类型答案但是这是一个工作(没有测试它)闭包:

inner_link.onclick = (function(link_num){
   return function(){
       alert('You clicked link '+link_num);
   };
})(i);

答案 1 :(得分:0)

您可以尝试:

window.onload = function(){
  var arbitrary_amount = 100;
  var the_list = document.getElementsByTagName('ul')[0];

  for(var i = 0; i < arbitrary_amount; i++){
    (function(){var natural_index = i + 1;
    var list_item = document.createElement('li');
    var inner_link = document.createElement('a');
    inner_link.setAttribute('href', '#');
    inner_link.innerHTML = "Link "+natural_index;

    inner_link.onclick = function(){
      return function(link_num){
        alert('You clicked link '+link_num);
      }(i);
    };

    list_item.appendChild(inner_link);
    the_list.appendChild(list_item);})();
  }


};

答案 2 :(得分:0)

您的代码在Firefox 3.5.5和Chrome 4.0.249.64中正常运行。

答案 3 :(得分:0)

这是因为您为onclick处理程序创建的每个闭包都共享相同的环境。执行onclick回调函数时,每个函数都会引用i的最后一个值。

已经有各种解决方案,所以我不会在这里重复,但我们的想法是创建不共享相同环境的其他闭包。

这是一个常见的错误。查看此MDC article以获取更多见解。

答案 4 :(得分:0)

<!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" xml:lang="en" lang="en">


<head>


<title>Just testing</title>


<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />


</head>
<body>



<div id="test1">
Testing
</div>




<script type="text/javascript">


//  self-invoking function


(function makeHR(){
      var newHR = document.createElement('hr');
      document.getElementById('test1').appendChild(newHR);
})();





function makeLink(j){


      var link =document.createElement("a");


  link.innerHTML ="<br>Link test " +j;


  link.setAttribute('href', '#');

  link.onclick = (function(link_num){


   return function(){


   alert('You clicked link '+link_num);

   };


  })(j);

  document.body.appendChild(link);
}


for (var i=1; i<4; i++) {

   makeLink(i);

}


</script>


</body>

</html>