Вебсправочник
Основы веб-разработки

Живые и статические коллекции DOM: почему меняется length

Некоторые результаты поиска DOM автоматически отражают изменения документа, другие сохраняют исходный набор найденных узлов. Это различие важно при добавлении элементов и удалении их в цикле.

Назначение

Некоторые результаты поиска DOM автоматически отражают изменения документа, другие сохраняют исходный набор найденных узлов. Это различие важно при добавлении элементов и удалении их в цикле.

Как это работает

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

Пример

const box = document.createElement("div");
box.innerHTML = '<p class="item">Первый</p>';
document.body.append(box);
const snapshot = box.querySelectorAll(".item");
const live = box.getElementsByClassName("item");
const next = document.createElement("p");
next.className = "item";
next.textContent = "Второй";
box.append(next);
console.log(snapshot.length, live.length);
box.remove();

Что должно получиться

Статический результат сохраняет длину 1, живая коллекция показывает 2. В конце учебный контейнер удаляется. InnerHTML здесь содержит только фиксированную авторскую строку, а новый текст добавляется через textContent.

Граница применения и частая ошибка

Статический список не делает копии самих элементов: его ссылки всё ещё указывают на реальные узлы. При удалении из живой коллекции индексы могут сдвигаться, и обычный прямой цикл способен пропустить элементы. Для стабильного набора используйте Array.from.

Самостоятельная проверка

Повторите поиск querySelectorAll после добавления и сравните длину нового результата. Затем удалите первый элемент и посмотрите оба набора. Объясните, почему NodeList нельзя всегда считать живым только по названию типа.

Самостоятельный учебный материал. Техническая документация: первоисточник по теме ↗. Если результат отличается, проверьте код и версию браузера.