addEventListener 使用 for 循环给了我一个未定义的结果
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);
让我们来看看迭代。
-
i = 0
,匹配条件i<len
,它继续执行代码块并在此之后执行i++
,这使得i=1
; -
i = 1
现在,匹配条件i<len
,它继续执行代码块并在此之后执行i++
,这使得i=2
; -
i = 2
现在,无法匹配条件i<len
并停止迭代。
因此,在转到步骤 3 之前,您已经设置了i=2
。所以你循环后的最后一console.log
for
会说, 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
关键字来做同样的事情。您所要做的就是将var
替换为 let
.您还可以在 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
值
- 变量转换为另一个“未定义”的变量
- getDataAsJSON()在PHP中是一个未定义的函数,但许多解释如何使用JSONP的网站都说要使用它
- 所以这是说我的法定对象中有一个未定义的变量
- 为什么在这个数组的末尾会有一个未定义的
- 为什么我得到一个未定义的回报
- Router.use()需要中间件函数,但得到了一个未定义的函数
- 使用jQuery'在数组中循环;s中的每一个都会在生成字符串时在开头产生一个未定义的值
- 如果定义了值,为什么会得到一个未定义的值?使用 eval()
- 无论如何,在Visual Studio智能感知中定义一个未定义的对象
- 角度过滤器分组依据过滤器返回一个“未定义”字段
- 如果我在 Filter() 函数中使用索引,我会得到一个未定义的引用错误吗?
- 另一个未定义的JavaScript问题
- 我得到一个未定义而不是文件名
- 为什么我的 push() 方法不断在我的数组中插入一个“未定义”的元素
- addEventListener 使用 for 循环给了我一个未定义的结果
- Promise.all 在完成之前返回一个未定义和解析的数组
- Angular JS给出了一个未定义的函数错误
- 我得到一个未定义的索引
- JS说我有一个未定义的对象.真的需要一些帮助来解决这个问题吗
- Ajax 调用给了我一个未定义 - 未定义的错误