HTMLCollection и NodeList

Время чтения: меньше 5 мин

Кратко

Секция статьи "Кратко"

HTMLCollection и NodeList — это очень похожие на массив коллекции. Они хранят элементы веб-страницы (узлы DOM). NodeList может хранить любые типы узлов, а HTMLCollection — только узлы HTML элементов. К элементам коллекций можно обращаться по индексу, но у них нет привычных методов массива.

HTMLCollection возвращают методы getElementsByTagName и getElementsByClassName.

NodeList возвращают методы querySelectorAll и childNodes.

Полный список всех методов, возвращающих типы NodeList или HTMLCollection можно узнать в стандарте DOM.

Как понять

Секция статьи "Как понять"

HTMLCollection возвращают методы, которые работают с DOM — представлением HTML-кода страницы в JavaScript.

Полученная один раз коллекция всегда остаётся актуальной — JavaScript будет обновлять её в случае, если на странице появляется подходящий элемент. Поэтому HTMLCollection называют «живой» коллекцией.

Например, единожды получив коллекцию мы можем не заботиться о её поддержке:

Открыть демо в новой вкладке

NodeList работает почти так же, как и HTMLCollection.

Разница:

  1. NodeList может хранить любые типы узлов, например текстовые узлы и комментарии, а HTMLCollection — только узлы HTML элементов;
  2. HTMLCollection позволяет обращаться к элементам не только по индексу, но и по имени с помощью метода namedItem;
  3. NodeList может быть не только «живой» коллекцией, но и статической. Такая коллекция не обновляется при появлении на странице новых элементов.

«Живой» NodeList возвращают методы getElementsByName и childNodes.

Статический NodeList возвращает метод querySelectorAll.

На практике

Секция статьи "На практике"

Николай Лопин

Секция статьи "Николай Лопин"

🛠 Используй индексы для получения отдельных элементов коллекции:

        
          
          let paragraphs = document.getElementsByTagName("p")console.log(paragraphs[0])
          let paragraphs = document.getElementsByTagName("p")
console.log(paragraphs[0])

        
        
          
        
      

🛠 Если нужно обойти все элементы в цикле, то можно написать классический цикл for:

        
          
          let paragraphs = document.getElementsByTagName("p")for (let i = 0; i < paragraphs.length; ++i) {  console.log(paragraphs[i].id) // печатаем значение атрибута id элемента}
          let paragraphs = document.getElementsByTagName("p")
for (let i = 0; i < paragraphs.length; ++i) {
  console.log(paragraphs[i].id) // печатаем значение атрибута id элемента
}

        
        
          
        
      

Другой вариант — воспользоваться синтаксисом for..of:

        
          
          let paragraphs = document.getElementsByTagName("p")for (let item of paragraphs) {  console.log(item.id)}
          let paragraphs = document.getElementsByTagName("p")
for (let item of paragraphs) {
  console.log(item.id)
}

        
        
          
        
      

🛠 Когда пишешь цикл с HTMLCollection убедись, что подходящие элементы не добавляются или удаляются со страницы в момент работы цикла. Так как коллекция живая, её обновление во время цикла может создать бесконечный цикл.

🛠 Если очень нужны методы массива, то преобразуй HTMLCollection или NodeList в массив с помощью Array.from.

        
          
          let paragraphs = document.getElementsByTagName("p")let array = Array.from(paragraphs)console.log(array.pop())
          let paragraphs = document.getElementsByTagName("p")
let array = Array.from(paragraphs)

console.log(array.pop())

        
        
          
        
      

Такое преобразование обычно не требуется. Подумай, точно ли оно подходит под твою задачу.