简体   繁体   English

Javascript - 添加eventlistener时未定义的数组元素

[英]Javascript - undefined array element when adding eventlistener

I am fairly new to javascript and I am trying to grab all the "td" elements in the DOM and add a click event to them. 我是javascript的新手,我试图抓住DOM中的所有“td”元素并向它们添加一个click事件。 When the code finishes executing, i can see I have 37 elements in cells array, but when I click the element, I get "clicked td37 undefined" in my console statement no matter which element is clicked. 当代码完成执行时,我可以看到我在单元格数组中有37个元素,但是当我单击该元素时,无论点击哪个元素,我都会在控制台语句中“点击td37 undefined”。 I do not have a clue what is wrong and any help would be appreciated. 我不知道什么是错的,任何帮助将不胜感激。

<script>
window.addEventListener("DOMContentLoaded", createEventListeners, false);

function createEventListeners() {
   var cells = document.getElementsByTagName("td");
   console.log(cells);

   for (var i = 0; i < cells.length; i++) {
      cells[i].addEventListener("click", function () {
      console.log("clicked td" +  i + " " + cells[i]);

      }, false);
   }

 }
</script>

At the end of the loop, the value of i will be the cells.length , so cells[i] is undefined. 在循环结束时, i的值将是cells.length ,因此cells[i]是未定义的。 You need to wrap them in a function so that i is the value you want. 你需要将它们包装在一个函数中,这样i就是你想要的值。 Read more about closure here 阅读更多关于闭包的信息

function createEventListeners() {
  var cells = document.getElementsByTagName("td");

  for (var i = 0; i < cells.length; i++) {
    (function(i) {
      cells[i].addEventListener("click", function () {
        console.log("clicked td" +  i + " " + cells[i]);
      }, false);
    }(i));
}

This is a scope issue. 这是一个范围问题。 You need a closure. 你需要一个关闭。 By the time any Event in your loop is called, i looks for it's last know value, which happens to be it's value at the end of the loop. 当你的循环中的任何Event被调用时, i查找它的最后一个已知值,这恰好是它在循环结束时的值。 Solution: 解:

var pre = onload; // previous onload
onload = function(){
  if(pre)pre();
  function createEventListeners(){
    var cells = document.getElementsByTagName('td');
    for(var i=0,l=cells.length; i<l; i++){
      (function(i){
        cells[i].addEventListener('click', function(){
          console.log('i is at position:'+i));
        }, false);
      })(i);
    }
  }
  window.addEventListener('DOMContentLoaded', createEventListeners, false);
}

At the end of your loop, i is always the length of the array for anything you click on and since they're zero indexed, no element with that index exists. 在循环结束时,对于您点击的任何内容, i总是数组的长度,因为它们是零索引的,所以不存在具有该索引的元素。 For example, if there are 10 elements, they're indexed as 0-9, but when you click any of them, i is always 10. 例如,如果有10个元素,则它们被索引为0-9,但是当您单击其中任何一个时, i总是10。

This question+answers are a great example of when and how to use closures. 这个问题+答案是何时以及如何使用闭包的一个很好的例子。 Since this question is tagged with jQuery , the each function would be a way to do it in jQuery . 由于这个问题是标记jQuery中, each功能将是一个办法做到这一点的jQuery When you use each , it conveniently closes over what you are eaching through, so this would also work: 当你使用each ,它可以方便地关闭你正在经历的东西,所以这也可以工作:

$(document).ready(function () {
    var $tds = $('td');
    $tds.each(function (i, td) {
        $(td).click(function () {
            console.log(i, td);
        });
    });
});

And also, there is a way to do it without closures. 而且,有一种方法可以在没有闭包的情况下完成。 If you store the value of the iterator onto the element itself via a data attribute, it stores a copy of the value, rather than a reference, so it retains the value of i at the time it was assigned: 如果通过数据属性将迭代器的值存储到元素本身,它会存储值的副本而不是引用,因此它在分配时保留i的值:

window.addEventListener("DOMContentLoaded", createEventListeners, false);
function createEventListeners() {
    var cells = document.getElementsByTagName("td");
    console.log(cells);

    for (var i = 0; i < cells.length; i++) {
        cells[i].setAttribute('data-i', i);
        cells[i].addEventListener("click", function () {
            var i = this.getAttribute('data-i');
            console.log("clicked td" + i + " " + cells[i]);

        }, false);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM