Почему списки узлов содержат дополнительные неопределенные элементы, которые не отражены в его свойстве длины?

Фон:


Я столкнулся с очень странным явлением при работе со списком узлов. Я хотел использовать 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 проходит через числовые индексы и не учитывает перечислимые свойства. Вот почему гораздо надежнее использовать прежний способ.

Другие вопросы по тегам