W3docs

JavaScript — выбор элементов DOM

Узнайте, как выбирать элементы DOM в JavaScript с помощью getElementById, querySelector, querySelectorAll, getElementsByClassName, matches и closest — с примерами и советами по применению каждого метода.

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

Что означает «выбрать элемент»

Document Object Model (DOM) — это живое древовидное представление HTML-документа, которое строит браузер. Каждый тег становится объектом-узлом, который можно читать и изменять из JavaScript. Выбор — это процесс нахождения одного или нескольких таких узлов, чтобы сохранить ссылку на них в переменной:

const heading = document.querySelector('h1');
// `heading` now points at the real <h1> on the page.

Получив такую ссылку, вы можете делать всё остальное — читать атрибуты и свойства, изменять стили, добавлять обработчики событий.

Методы выбора делятся на две группы:

  • Поиск по ID / классу / тегу — быстрый; возвращает живые коллекции (за исключением getElementById).
  • Поиск по CSS-селекторам (querySelector, querySelectorAll) — гибкий; принимает любой CSS-селектор; возвращает статический результат.

Выбор одного элемента по ID: getElementById

Самый быстрый способ получить единственный элемент — обратиться к нему по уникальному id. Метод возвращает элемент или null, если элемент с таким ID не существует.

const element = document.getElementById('example');
element.textContent = 'You selected the element by its ID!';

Поскольку ID должны быть уникальными, getElementById возвращает один элемент (а не коллекцию) и является наиболее прямым и быстрым способом поиска.

Информация

Если совпадений нет, getElementById возвращает null. Обращение к свойству null вызовет TypeError: Cannot read properties of null. Защититесь от этого: const el = document.getElementById('maybe'); if (el) { /* ... */ }.

Выбор по имени класса: getElementsByClassName

Этот метод возвращает живую HTMLCollection всех элементов с указанным классом. «Живая» означает, что коллекция автоматически обновляется при изменении DOM.

const elements = document.getElementsByClassName('example');
Array.from(elements).forEach((element, index) => {
    element.textContent = `Element ${index + 1} changed!`;
});

HTMLCollection похожа на array, но не является им, поэтому у неё нет методов forEach/map. Перед использованием этих методов преобразуйте коллекцию с помощью Array.from() (или оператора расширения [...elements]).

Информация

Поскольку коллекция живая, цикл for (let i = 0; i < c.length; i++) с удалением совпадающих элементов внутри может пропускать элементы — длина коллекции уменьшается прямо во время итерации. Сделайте снимок с помощью Array.from(), если планируете изменять DOM в процессе перебора.

Выбор по имени тега: getElementsByTagName

Выбирает все элементы с указанным именем тега и возвращает живую HTMLCollection.

const paragraphs = document.getElementsByTagName('p');
for (let i = 0; i < paragraphs.length; i++) {
    paragraphs[i].style.backgroundColor = 'yellow';
}

Передайте '*', чтобы охватить все элементы страницы. Это удобно, когда нужно обработать все теги одного типа — например, выделить каждый абзац.

Выбор по атрибуту name: getElementsByName

Возвращает живую NodeList элементов с одинаковым атрибутом name. Чаще всего используется для элементов форм — например, для всех переключателей одной группы:

const options = document.getElementsByName('plan');
options.forEach((radio) => {
    radio.addEventListener('change', () => {
        console.log('Selected plan:', radio.value);
    });
});

Подробнее о работе с формами читайте в разделе работа с формами в DOM.

Выбор с помощью CSS-селекторов: querySelector

querySelector возвращает первый элемент, соответствующий переданному CSS-селектору, или null, если совпадений нет. Это наиболее универсальный метод для выбора одного элемента.

const element = document.querySelector('.example');
element.style.backgroundColor = 'lightblue';

Поскольку метод принимает полный синтаксис CSS-селекторов, можно точно указать глубоко вложенный элемент: querySelector('nav ul li.active a') находит первую подходящую ссылку без цепочки нескольких вызовов.

Выбор всех совпадений: querySelectorAll

Возвращает статическую NodeList всех элементов, соответствующих селектору. В отличие от getElementsBy..., этот снимок не обновляется при последующих изменениях DOM.

const elements = document.querySelectorAll('.example');
elements.forEach((element, index) => {
    element.style.backgroundColor = 'lightgreen';
    element.textContent = `Element ${index + 1} highlighted!`;
});

NodeList имеет метод forEach, поэтому по ней можно итерировать напрямую. Для использования map/filter сначала преобразуйте её с помощью Array.from(elements).

Информация

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

Ограничение поиска областью элемента

Все методы querySelector* и getElementsBy* доступны не только на document, но и на отдельных элементах. Вызов метода на элементе ограничивает поиск потомками этого элемента:

const card = document.querySelector('.card');
const title = card.querySelector('.title'); // only inside .card

Ограничение области поиска ускоряет запросы и предотвращает случайное совпадение с элементами в других частях страницы.

Проверка элемента: matches

matches не возвращает элемент — он возвращает true/false в зависимости от того, соответствует ли данный элемент CSS-селектору. Метод идеально подходит для обработчиков событий и делегирования событий.

const element = document.getElementById('test');
if (element.matches('.example')) {
    element.style.color = 'red';
    element.textContent = 'Element matches the selector!';
}

Подъём по дереву: closest

closest начинает с самого элемента и поднимается по его предкам, возвращая ближайшего из них, соответствующего селектору (или null). Это самый удобный способ найти элемент-контейнер.

const element = document.getElementById('child');
const parent = element.closest('.outer');
parent.style.border = '2px solid red';
Информация

matches + closest — основа делегирования событий: добавьте один обработчик к контейнеру, а внутри него используйте event.target.closest('.item'), чтобы определить, какой дочерний элемент был нажат. Подробнее в разделе обработка событий в DOM.

Комбинирование селекторов для точного выбора

CSS-селекторы можно комбинировать, получая нужную точность без лишнего кода:

const element = document.querySelector('.example.special');
element.style.backgroundColor = 'pink';
element.textContent = 'Special element highlighted!';

Здесь .example.special соответствует элементу, который имеет оба класса. Можно комбинировать операторы (>, пробел для потомков, +, ~), селекторы атрибутов (input[type="email"]) и псевдоклассы (li:first-child).

Какой метод выбрать?

МетодВозвращаетЖивой?Лучше использовать для
getElementByIdодин элемент / nullн/подного элемента с известным уникальным ID
getElementsByClassNameHTMLCollectionживойвсех элементов с классом, отслеживая DOM
getElementsByTagNameHTMLCollectionживойвсех элементов с тегом
getElementsByNameNodeListживойэлементов форм с одинаковым name
querySelectorпервое совпадение / nullн/ппервого элемента по любому CSS-селектору
querySelectorAllNodeListстатическийстабильного снимка всех совпадений
matchesbooleanн/ппроверки соответствия элемента селектору
closestближайший предок / nullн/ппоиска элемента-контейнера

Практические рекомендации:

  • По умолчанию используйте querySelector / querySelectorAll — единый API с полной мощью CSS.
  • Используйте getElementById, когда у вас есть уникальный ID и нужен максимально быстрый поиск.
  • Прибегайте к живой коллекции (getElementsBy...) только тогда, когда вам действительно нужно отслеживать изменения DOM; в остальных случаях предпочитайте статический querySelectorAll.

Типичные ошибки

  • Результат null. getElementById, querySelector и closest возвращают null, когда совпадений нет. Всегда проверяйте результат перед использованием.
  • Запуск до создания DOM. Если скрипт выполняется в <head> до разбора элементов, выборки не находят ничего. Размещайте скрипты в конце <body>, используйте defer или ждите события DOMContentLoaded.
  • Коллекции — не array. У HTMLCollection нет метода forEach. У NodeList есть forEach, но нет map/filter. При сомнениях преобразуйте через Array.from().

Заключение

Выбор элементов — это отправная точка для любой работы с DOM. В большинстве случаев querySelector и querySelectorAll дают удобный и мощный CSS-ориентированный API; getElementById остаётся самым быстрым вариантом для уникальных ID; а matches и closest обеспечивают чистое делегирование событий. Освоив выбор элементов, переходите к манипуляциям с DOM и перемещению по DOM.

Информация

Замечание о производительности: все эти методы достаточно быстры для типичных страниц. Реальная нагрузка возникает при многократном их вызове в плотных циклах — кэшируйте результат выборки в переменной вместо повторных запросов. Статические NodeList из querySelectorAll избавляют от накладных расходов на отслеживание изменений, которые несут живые HTMLCollection.

Практика

Практика
Какие из следующих методов можно использовать для выбора элементов DOM в JavaScript?
Какие из следующих методов можно использовать для выбора элементов DOM в JavaScript?
Практика
Что возвращает document.querySelector('.box'), если элемента с классом 'box' нет?
Что возвращает document.querySelector('.box'), если элемента с классом 'box' нет?
Практика
Какой метод возвращает статическую коллекцию, которая НЕ обновляется при последующих изменениях DOM?
Какой метод возвращает статическую коллекцию, которая НЕ обновляется при последующих изменениях DOM?
Was this page helpful?