Почему списки узлов содержат дополнительные неопределенные элементы, которые не отражены в его свойстве длины?
Фон:
Я столкнулся с очень странным явлением при работе со списком узлов. Я хотел использовать getElementsByClassName или что-то подобное, а затем отсортировать его. Я решил, что одним из способов будет перебирать нодлист, помещать каждый элемент в массив и сортировать массив. (Это, кстати, сработало, но не так, как ожидалось). Я пытался использовать for (var i in nodeList)
перебирать, но он выдавал исключение для последних нескольких элементов, которые не были определены. странная часть, я мог бы вместо этого использовать for (var i = 0; i < nodeList.length; i++)
перебирать. Я только что проверил это снова и на странице stackru я запустил в своей консоли следующий код:
for (var i in document.getElementsByTagName("span"))
console.count("items");
console.log(document.getElementsByTagName("span").length);
Отсчитал до items: 382
но длина дала 380
, Как и ожидалось, когда я вошел document.getElementsByTagName("span")[380]
а также document.getElementsByTagName("span")[381]
они вернулись неопределенными. Это странное поведение не происходит в массивах (предоставлено, списки узлов и массивы различаются, но это доказывает, что это не отличается для циклов, вызывающих проблему).
вопрос:
Почему for(var i in nodeList)
конструкции ведут себя по-разному в списках узлов, возвращая пару неопределенных элементов в конце?
2 ответа
Два дополнительных свойства, которые for in
ловит операторы итерации:
- длина
- вещь
Позвольте мне привести простой пример. Допустим, на странице есть 3 элемента SPAN.
var spans = document.getElementsByTagName( 'span' );
Сейчас, spans
является объектом NodeList, который содержит 5 свойств:
- 0
- 1
- 2
- длина
- вещь
Первые 3 свойства являются индексами и содержат ссылки на эти элементы SPAN. Два других свойства - длина и элемент - являются двумя дополнительными свойствами. Все объекты NodeList имеют эти два свойства.
for in
оператор перебирает все 5 свойств объекта NodeList, что, вероятно, не то, что вам нужно. Поэтому пользуйтесь обычным for
заявление.
var i, span;
for ( i = 0; i < spans.length; i++ ) {
span = spans[i];
// do stuff with span
}
for-in перебирает все перечисляемые свойства объекта, такие как длина и элемент (это ваша ситуация). Вот откуда приходят еще два результата. Также будет перечислено все, что добавлено к прототипу объекта.
for проходит через числовые индексы и не учитывает перечислимые свойства. Вот почему гораздо надежнее использовать прежний способ.