Ответ 1
Описание
document.getElementsByClassName
возвращает HTMLCollection
, а не только массив элементов. Это означает, что коллекция живая, поэтому в этой конкретной ситуации она сохраняет требование, чтобы она всегда удерживала все элементы с классом "current".
Кстати, вы удаляете очень class
, от которого зависит коллекция, поэтому обновляем коллекцию. Было бы совершенно иначе, если бы вы устанавливали свойство value
(например) в цикле - коллекция не повлияла бы, потому что class
"current" не был удален. Было бы совершенно иначе, если бы вы были добавили класс, например el.className += " none";
, но это не так.
Отличное описание из документов MDN:
HTMLCollections в HTML DOM живут; они автоматически обновляются при изменении базового документа.
Подход 1
Легкий способ преодолеть все это pandemonium - это зацикливание назад.
var els = document.getElementsByClassName('current'),
i = els.length;
while (i--) {
els[i].className = 'none';
}
DEMO: http://jsfiddle.net/fAJgT/
(код в демо имеет setTimeout
, так что вы можете сначала увидеть исходный цвет рамки, а затем через 1,5 секунды увидеть его изменение)
Это работает, потому что он изменяет последний элемент в коллекции - когда он изменен (и автоматически удален), перейдите к элементу перед ним. Таким образом, он не страдает от последствий автоматического удаления.
Альтернативная настройка, выполняющая то же самое, такова:
for (i = els.length; i >= 0; i--) {
Подход 2
Другой ответ заставил меня понять, что вы можете просто постоянно работать над первым найденным предметом. Когда вы удаляете конкретный класс, элемент удаляется из коллекции, поэтому вам гарантируется, что первый элемент всегда является новым элементом в коллекции. Поэтому проверка свойства length
должна быть безопасным условием проверки. Вот пример:
var els = document.getElementsByClassName('current');
while (els.length) {
els[0].className = 'none';
}
DEMO: http://jsfiddle.net/EJLXe/
В основном это говорит: "Пока есть элементы в коллекции, измените первый (который будет удален после изменения)". Я действительно не рекомендовал бы использовать этот метод, потому что он работает только , потому что вы в конечном итоге изменяете коллекцию. Это будет бесконечно циклически, если вы не удаляете конкретный класс или с обычным массивом или неживой коллекцией (без splice
ing).
Подход 3
Другим вариантом является slice
(мелкая копия) сборка в массив и цикл, который обычно выполняется. Но я не вижу причин для этого. Вот пример:
var els = document.getElementsByClassName('current'),
sliced = Array.prototype.slice.call(els), i;
for (i = 0; i < sliced.length; i++) {
sliced[i].className = 'none';
}
DEMO: http://jsfiddle.net/LHe95/2/
Подход 4
Наконец, вы можете использовать document.querySelector
- он возвращает не-live NodeList
(поэтому вы можете циклически, как обычно), и даже имеет лучшую поддержку в браузеров, чем document.getElementsByClassName
. Вот пример:
var els = document.querySelectorAll('.current'),
i;
for (i = 0; i < els.length; i++) {
els[i].className = 'none';
}
DEMO: http://jsfiddle.net/xq8Xr/
Литература:
-
document.getElementsByClassName
: https://developer.mozilla.org/en-US/docs/DOM/document.getElementsByClassName -
HTMLCollection
: https://developer.mozilla.org/en-US/docs/DOM/HTMLCollection -
slice
: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/slice -
querySelectorAll
: https://developer.mozilla.org/en-US/docs/DOM/Document.querySelectorAll