При добавлении прослушивателя событий вы создаете замыкание. Каждый обработчик событий имеет переменную i
в своей области видимости. К сожалению, это та же самая переменная i
, которая увеличивается с помощью вашего цикла for.
В конце цикла каждый обработчик событий имеет в своей области видимости переменную i
, значение которой теперь равно 6. Это приводит к тому, что li[i]
не определено при запуске события.
Вы можете решить это, либо:
- не использует
i
в вашем обработчике, например, с помощью предоставленной переменной event
, которая ссылается на событие. И через это, получает целевой элемент:
var li = document.querySelectorAll("li");
for (var i = 0; i < li.length; i++) {
li[i].addEventListener("click", function(event) {
event.target.classList.toggle("done");
})
}
.done {
text-decoration: line-through;
}
<h1>Shopping List</h1>
<ul style="list-style-type:square">
<li>Pencil</li>
<li>Paper</li>
<li>Eraser</li>
<li>Table Lamp</li>
<li>Comb</li>
</ul>
- объявление
i
с let
вместо var
в вашем цикле for. Это приведет к тому, что каждое ваше закрытие будет иметь различную привязку с i
:
var li = document.querySelectorAll("li");
for (let i = 0; i < li.length; i++) {
li[i].addEventListener("click", function() {
li[i].classList.toggle("done");
})
}
.done {
text-decoration: line-through;
}
<h1>Shopping List</h1>
<ul style="list-style-type:square">
<li>Pencil</li>
<li>Paper</li>
<li>Eraser</li>
<li>Table Lamp</li>
<li>Comb</li>
</ul>
- присоединение слушателя события к UL. Это было бы моим любимым:
var ul = document.querySelector("ul");
ul.addEventListener("click", function(event) {
event.target.classList.toggle("done");
}, true);
.done {
text-decoration: line-through;
}
<h1>Shopping List</h1>
<ul style="list-style-type:square">
<li>Pencil</li>
<li>Paper</li>
<li>Eraser</li>
<li>Table Lamp</li>
<li>Comb</li>
</ul>
Подробнее о закрытиях JavaScript.