Addeventlistener Using For Loop Gives Me An Undefined Result
Solution 1:
This is because, i
is a variable defined outside your event handler function, which is incremented by each iteration. So when you finish the iterations of the for
loop, the value of i
is equal tolen
, which causes li[i]
to be undefined
. And if you ask me why it's value is not considered during the iteration, it's because your event handler function is only executed when the event occurs (not when you are setting the event handlers by for
loop). So you can make a variable inside the function scope which won't be changed by iteration. Better use this
from inside the event handler to get the same thing.
for(var i=0,len=li.length; i<len; i++){
li[i].addEventListener('click',function(e){
e.preventDefault();
alert(this);
vardata = this.dataset.info;
showDiv.innerHTML = data;
},false);
}
Understanding the for loop
Why the value of i
is equal to len
after for
loop is finished? Let's have a simpler example to make you understand the situation.
varlen = 2;
for(var i=0; i<len; i++; {
//Do anything here
}
console.log("after for loop: i = " + i);
Lets's go through the iterations.
i = 0
, matches the conditioni<len
, which proceeds with executing the code block and executesi++
after that, which makesi=1
;i = 1
now, matches the conditioni<len
, which proceeds with executing the code block and executesi++
after that, which makesi=2
;i = 2
now, fails to match the conditioni<len
and stops the iteration.
So, you have set the i=2
before you go to step 3. So your final console.log
after for
loop will say, after for loop: i = 2
Solution 2:
This occurs because of scope. Inside the EventListener
, you have an anonymous function, because of this, you are no longer in the scope of li
. However, you can refer to it with the this
keyword. See the alert that I've replaced in your code.
(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);
}
}());
<divclass="showDiv">Show data: </div><divclass="outerDiv"><ulclass="idiv"><lidata-info="datashow"><ahref="">111</a></li><lidata-info="dataHide"><ahref="">222</a></li><lidata-info="dataToggle"><ahref="">333</a></li></ul></div>
Solution 3:
Another approach in addition to the answers of other posters is to use a local scope with function
. In JavaScript function
is the most reliable way of creating a new scope. Taking the above example,
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 have created a new scope that that will isolate the value of variable i
. If you're using ES6 you can use let
keyword to do just the same thing. All you have to do is replace var
with let
. You can also use let
in a for
loop that will give you a whole new scope that is local to for
loop.
Solution 4:
You need to refer to the particular li
on which you want to attach the event
(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);
}
}());
When click
will be executed i
will have value as 3 (in your case) so li[i]
will be different. You can check the console of THIS to check value of i
on click
event
Post a Comment for "Addeventlistener Using For Loop Gives Me An Undefined Result"