为什么这段代码会给我一个未定义的结果? 我已在网络浏览器中测试过。它告诉我li [i]是未定义的。而且我不知道为什么以及如何。 我知道关闭。也许它应该弹出字符串' dataToggle'每次我点击每个li元素;但有人可以帮助我了解这个具体问题的更多细节,以及您认为理解这个问题的重要性? 感谢
(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);
}
}());
&#13;
<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>
&#13;
答案 0 :(得分:3)
这是因为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);
}
为什么i
循环结束后len
的值等于for
?让我们有一个更简单的例子让你了解情况。
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
答案 1 :(得分:1)
这是因为范围。在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);
}
}());
&#13;
<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>
&#13;
答案 2 :(得分:1)
除了其他海报的答案之外,另一种方法是使用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
。您还可以在let
循环中使用for
,这将为您提供for
循环本地的全新范围。
答案 3 :(得分:0)
您需要参考您要附加活动的特定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的控制台,查看i
活动中click
的值