Что я делаю не так на этом простом замыкании - PullRequest
3 голосов
/ 18 января 2010

это может быть лишение сна, но я не могу понять, почему это не работает. Я хочу, чтобы onclick возвращал значение i из цикла for, который создал элемент и применил обработчик событий. Положили его в замыкание, и оно все еще поворачивает максимальное число итераторов.

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 ]

8 голосов
/ 18 января 2010

вы используете закрытие неправильно ... я не могу дать вам ответ типа гуру относительно того, что на самом деле происходило, но вот рабочее закрытие (не проверяло):

inner_link.onclick = (function(link_num){
   return function(){
       alert('You clicked link '+link_num);
   };
})(i);
0 голосов
/ 26 августа 2012
<!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>
0 голосов
/ 18 января 2010

Это потому, что каждое замыкание, которое вы создаете для обработчика onclick, использует одну и ту же среду.Когда выполняется функция обратного вызова onclick, каждая ссылается на последнее значение i.

Уже есть различные решения, поэтому я не буду повторять это здесь, но идея заключается вдополнительные замыкания, которые не разделяют одно и то же окружение.

Это распространенная ошибка.Оформите эту статью MDC для получения дополнительной информации.

0 голосов
/ 18 января 2010

Ваш код корректно работает для меня в Firefox 3.5.5 и Chrome 4.0.249.64.

0 голосов
/ 18 января 2010

Вы можете попробовать:

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);})();
  }


};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...