querySelectorAll и NodeList

querySelectorAll возвращает статичную NodeList всех элементов, соответствующих CSS-селектору; в отличие от живых HTMLCollection, NodeList не обновляется автоматически при изменении DOM.

Зачем нужно

querySelectorAll — универсальный метод поиска элементов, принимающий любой валидный CSS-селектор. Это позволяет заменить несколько специализированных методов (getElementById, getElementsByClassName, getElementsByTagName) одним. Понимание разницы между «живыми» и «статичными» коллекциями критично для предотвращения багов в динамических интерфейсах.

Где используется

  • Поиск элементов по любому CSS-селектору (вложенность, комбинаторы, псевдоклассы)
  • Батч-обработка группы элементов
  • Снимок DOM в конкретный момент времени
  • Чтение списка элементов без риска мутации при итерации

Основной контент

Базовое использование

// Все элементы с классом .item
const items = document.querySelectorAll('.item');

// NodeList поддерживает forEach напрямую
items.forEach(item => item.classList.add('active'));

// Сложные селекторы
const checked = document.querySelectorAll('input[type="checkbox"]:checked');
const navLinks = document.querySelectorAll('nav > ul > li > a');
const first3 = document.querySelectorAll('li:nth-child(-n+3)');

querySelector — первый совпадающий

// Возвращает первый элемент или null
const modal = document.querySelector('.modal');

if (modal) {
  modal.style.display = 'block';
}

// Поиск внутри элемента
const form = document.querySelector('#login-form');
const emailInput = form.querySelector('input[type="email"]');

NodeList vs HTMLCollection

const list = document.getElementById('myList');

// HTMLCollection — живая
const live = list.getElementsByTagName('li');

// NodeList — статичная
const static_ = list.querySelectorAll('li');

// Добавляем новый элемент
const li = document.createElement('li');
list.appendChild(li);

console.log(live.length);    // увеличилось
console.log(static_.length); // не изменилось

// NodeList не является массивом
console.log(static_ instanceof Array); // false
// Но поддерживает forEach, entries, keys, values
static_.forEach(el => console.log(el.textContent));

// Конвертация в массив для map, filter, reduce
const arr = Array.from(static_);
const texts = arr.map(el => el.textContent);

Производительность

// Поиск внутри элемента эффективнее, чем глобальный
const section = document.querySelector('#main-section');
const links = section.querySelectorAll('a'); // ищет только внутри section

// Для частых обращений — кэшируем результат
const buttons = document.querySelectorAll('.btn');
// Вызываем querySelectorAll один раз, не в цикле
buttons.forEach(btn => {
  btn.addEventListener('click', handleClick);
});

Частые ошибки

  • querySelectorAll не возвращает массив — методы map, filter, reduce недоступны напрямую. Используйте Array.from или spread [...].
  • Неверный CSS-селектор выбрасывает SyntaxError — оберните вызов в try/catch при динамическом формировании селектора.
  • Кэширование статичной NodeList — если DOM изменился, NodeList устарела. Для динамического контента пересчитывайте коллекцию или используйте живую HTMLCollection.

Связанные темы

Ресурсы