JavaScript JavaScript and the DOM Responding to User Interaction Listening for Events with addEventListener()

Brian Patrick
Brian Patrick
Pro Student 2,770 Points

Uncaught TypeError: Cannot read property 'textContent' of undefined

for(var i = 0; i < listItems.length; i++){

  listItems[i].addEventListener('mouseover', () =>{
    listItems[i].textContent = listItems[i].textContent.toUpperCase();                             

  listItems[i].addEventListener('mouseout', () => {
    listItems[i].textContent = listItems[i].textContent.toLowerCase();                            


It works outside of a loop but not inside the loop. Why?

5 Answers

Dave StSomeWhere
Dave StSomeWhere
19,791 Points

Pretty sure it is a JavaScript closure/scoping issue - your index i is resolved to the value at the end of the loop when it tries set the eventlistener and textContent.

Try "let" instead of "var" (works for me with let).

MDN let

Jaspal Singh
Jaspal Singh
13,525 Points

Hi Brian

I think it is not recognizing the dom element on which your applying the textContent property. So pls check that you have properly selected or referenced the listItems with the help of getElementsByTagName.

Steven Parker
Steven Parker
179,789 Points

The value of "i" is not the same when the event happens as when the handler is attached. Dave has the right idea and you can correct this by using "let" instead of "var" to constrain the scope and give each handler its own value for "i".

@Dave varmutant was right!

Just use LET instead of VAR and you should be fine.

Bradley Demerich
Bradley Demerich
11,688 Points

Use let instead, and try to refactor your function for a better experience:

const listItems = document.getElementsByTagName('li');

for(let i = 0; i < listItems.length; i += 1) {
 let liItem = listItems[i];
liItem.addEventListener('mouseover',() => {
   liItem.textContent = liItem.textContent.toUpperCase();

liItem.addEventListener('mouseout',() => {
   liItem.textContent = liItem.textContent.toLowerCase();
}  ```