繁体   English   中英

使用for循环的addEventListener给我一个不确定的结果

[英]addEventListener using for loop gives me an undefined result

为什么这段代码给我一个不确定的结果? 我已经在网络浏览器中进行了测试。 它告诉我li [i]是未定义的。 而且我不知道为什么以及如何。 我知道关闭。 也许每次我单击每个li元素时,它都应该弹出字符串“ dataToggle”。 但是有人可以帮助我提供有关此特定问题的更多详细信息,您认为理解该问题重要的是什么? 谢谢

 (function(){ var innerDiv = document.getElementsByClassName('showDiv')[0]; //var li = document.querySelectorAll('ul.idiv li'); var li = document.getElementsByTagName('li'); for(var i=0,len=li.length; i<len; i++){ li[i].addEventListener('click',function(e){ e.preventDefault(); alert(li[i]); var data = li[i].dataset.info; showDiv.innerHTML = data; },false); } }()); 
 <div class="showDiv">Show data: </div> <div class="outerDiv"> <ul class="idiv"> <li data-info="datashow"><a href="">111</a></li> <li data-info="dataHide"><a href="">222</a></li> <li data-info="dataToggle"><a href="">333</a></li> </ul> </div> 

这是因为, i是在事件处理程序函数外部定义的变量,每次迭代都会递增。 因此,当您完成for循环的迭代时, i的值等于len ,这将导致li[i] undefined 而且,如果您问我为什么在迭代过程中不考虑它的值,那是因为您的事件处理程序功能仅在事件发生时才执行(而不是在您通过for循环设置事件处理程序时执行)。 因此,您可以在函数范围内创建一个变量,该变量不会被迭代更改。 最好从事件处理程序内部使用this来获得相同的结果。

for(var i=0,len=li.length; i<len; i++){
   li[i].addEventListener('click',function(e){
         e.preventDefault();
         alert(this);
         var data = this.dataset.info;
         showDiv.innerHTML = data;
   },false);
} 

了解for循环

为什么在for循环结束后i的值等于len 让我们用一个简单的例子来使您了解情况。

var len = 2;
for(var i=0; i<len; i++; {
    //Do anything here
}
console.log("after for loop: i = " + i);

让我们来看一下迭代。

  1. i = 0 ,匹配条件i<len ,条件继续执行代码块,然后执行i++ ,使i=1
  2. 现在i = 1 ,匹配条件i<len ,条件执行代码块,然后执行i++ ,这使i=2
  3. 现在i = 2 ,无法满足条件i<len并停止迭代。

因此,在执行步骤3之前,您已经设置了i=2因此, for循环之后的最终console.log将显示, after for loop: i = 2

发生这种情况是由于范围。 EventListener内部,您具有匿名函数,因此,您不再在li的范围内。 但是,您可以使用this关键字来引用它。 查看代码中我已替换的警报。

 (function(){ var innerDiv = document.getElementsByClassName('showDiv')[0]; //var li = document.querySelectorAll('ul.idiv li'); var li = document.getElementsByTagName('li'); for(var i=0,len=li.length; i<len; i++){ li[i].addEventListener('click',function(e){ // you are now inside a different function block here. e.preventDefault(); alert(this.innerHTML); var data = li[i].dataset.info; showDiv.innerHTML = data; },false); } }()); 
 <div class="showDiv">Show data: </div> <div class="outerDiv"> <ul class="idiv"> <li data-info="datashow"><a href="">111</a></li> <li data-info="dataHide"><a href="">222</a></li> <li data-info="dataToggle"><a href="">333</a></li> </ul> </div> 

除了其他发布者的答案之外,另一种方法是使用具有function的局部范围。 在JavaScript中, function是创建新范围的最可靠方法。 以上述示例为例,

for (var i = 0; i < li.length; i++) {
    (function(i) {
        var j = i;
        li[j].addEventListener('click', function(e) {
        e.preventDefault();
        var data = li[j].dataset.info;
        showDiv.innerHTML = data;
    }, false);
  })(i);
}

我创建了一个新的作用域,它将隔离变量i的值。 如果您使用的是ES6,则可以使用let关键字执行相同的操作。 您要做的就是用let替换var 您还可以在for循环中使用let ,这将为您提供for循环本地的全新作用域。

您需要参考要附加事件的特定li

(function(){
      var innerDiv = document.getElementsByClassName('showDiv')[0];
       var li = document.getElementsByTagName('li'); 
          for(var i=0,len=li.length;i<len;i++){
           var thisLi = li[i];
           thisLi.addEventListener('click',function(e){
                 e.preventDefault();
                 alert(thisLi.innerHTML);
                 var data = thisLi.getAttribute('data-info');
                 innerDiv.innerHTML = data;
           },false);
      } 
    }());

click将被执行时, i值为3(在您的情况下),因此li[i]会有所不同。 您可以检查THIS的控制台以检查click事件中i

暂无
暂无

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

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