Ответ 1
Резюме (добавлено в декабре 2018 г.)
Никогда не используйте for/in
для итерации nodeList или HTMLCollection. Причины, чтобы избежать этого, описаны ниже.
Все последние версии современных браузеров (Safari, Firefox, Chrome, Edge) все поддерживают for/of
итераций в списках DOM, таких как nodeList
или HTMLCollection
.
Вот пример:
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
Чтобы включить старые браузеры (включая такие, как IE), это будет работать везде:
var list= document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
console.log(list[i].id); //second console output
}
Пояснение, почему вы не должны использовать for/in
for/in
предназначен для итерации свойств объекта. Это означает, что он вернет все итерируемые свойства объекта. Хотя может показаться, что он работает для массива (возвращая элементы массива или элементы псевдомассива), он также может возвращать другие свойства объекта, отличные от ожидаемых от элементов, подобных массиву. И, угадайте, что, HTMLCollection
или объект nodeList
могут иметь и другие свойства, которые будут возвращены с итерацией for/in
. Я только что попробовал это в Chrome, и повторяя его так, как вы его повторяли, получит элементы в списке (индексы 0, 1, 2 и т.д.), Но также получит свойства length
и item
. Итерация for/in
просто не будет работать для HTMLCollection.
Смотрите http://jsfiddle.net/jfriend00/FzZ2H/ почему вы не можете перебирать в HTMLCollection с for/in
.
В Firefox ваша итерация for/in
будет возвращать эти элементы (все итерируемые свойства объекта):
0
1
2
item
namedItem
@@iterator
length
Надеюсь, теперь вы можете понять, почему вы хотите использовать вместо for (var я = 0; я < list.length; i++)
чтобы вы просто получили 0
, 1
и 2
в своей итерации.
Ниже приводится эволюция эволюции браузеров за период 2015-2018 гг., Которая дает вам дополнительные способы итерации. В современных браузерах ничего из этого не требуется, поскольку вы можете использовать опции, описанные выше.
Обновление для ES6 в 2015 году
В ES6 добавлен Array.from Array.from()
, который преобразует Array.from()
структуру в реальный массив. Это позволяет прямо перечислять список следующим образом:
"use strict";
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
console.log(item.id);
});
Рабочая демонстрация (в Firefox, Chrome и Edge на апрель 2016 г.): https://jsfiddle.net/jfriend00/8ar4xn2s/
Обновление для ES6 в 2016 году
Теперь вы можете использовать ES6 for/of construct с NodeList
и HTMLCollection
, просто добавив это в свой код:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
Затем вы можете сделать:
var list = document.getElementsByClassName("events");
for (var item of list) {
console.log(item.id);
}
Это работает в текущей версии Chrome, Firefox и Edge. Это работает, потому что он присоединяет итератор Array к прототипам NodeList и HTMLCollection, так что, когда for/of итерирует их, он использует итератор Array для их итерации.
Рабочая демонстрация: http://jsfiddle.net/jfriend00/joy06u4e/.
Второе обновление для ES6 в декабре 2016 года
По состоянию на декабрь 2016 года поддержка Symbol.iterator
была встроена в Chrome v54 и Firefox v50, поэтому приведенный ниже код работает сам по себе. Он еще не встроен в Edge.
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
Рабочая демонстрация (в Chrome и Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/
Третье обновление для ES6 в декабре 2017 года
По состоянию на декабрь 2017 г. эта возможность работает в Edge 41.16299.15.0 для nodeList
как в document.querySelectorAll()
, но не для HTMLCollection
как в document.getElementsByClassName()
поэтому необходимо вручную назначить итератор, чтобы использовать его в Edge для HTMLCollection
. Это полная загадка, почему они исправляют один тип коллекции, а не другой. Но вы можете по крайней мере использовать результат document.querySelectorAll()
с ES6 for/of
синтаксиса в текущих версиях Edge сейчас.
Я также обновил вышеупомянутый jsFiddle, чтобы он тестировал HTMLCollection
и nodeList
отдельности и записывал выходные данные в самом jsFiddle.
Четвертое обновление для ES6 в марте 2018 года
Для mesqueeeb, поддержка Symbol.iterator
также встроена в Safari, так что вы можете использовать for (let item of list)
для document.getElementsByClassName()
или document.querySelectorAll()
.
Пятое обновление для ES6 в апреле 2018 года
Очевидно, поддержка итерации HTMLCollection
с for/of
появится в Edge 18 осенью 2018 года.
Шестое обновление для ES6 в ноябре 2018 года
Я могу подтвердить, что с Microsoft Edge v18 (который включен в Windows Update 2018 года) теперь вы можете выполнять итерацию HTMLCollection и NodeList с for/of в Edge.
Итак, теперь все современные браузеры содержат встроенную поддержку for/of
итераций объектов HTMLCollection и NodeList.