В этой статье мы разберём типы узлов в DOM, а также чем они являются. Познакомимся с некоторыми свойствами и методами узлов, и изучим иерархию их классов. Кроме этого познакомимся с основами исследования DOM в браузере Chrome.
- Examples
- Методы для выбора HTML-элементов
- Методы getElement(s)By* для выбора HTML-элементов
- More Examples
- Типы и имена DOM-узлов
- Return Value
- Перебор коллекции HTML-элементов
- Warning
- Browser Support
- Description
- GetElementsBy* и живые HTML-коллекции
- Классы DOM-узлов
- Related Pages
- Syntax
- QuerySelector
- QuerySelectorAll
- Задачи
- Standard Properties and Events
- Body Object
- Access a Body Object
- Create a Body Object
- Matches, closest и contains
Examples
Get the HTML content of a document:
const myBody = document.body.innerHTML;
Try it Yourself »
Change the background color of a document:
document.body.style.backgroundColor = «yellow»;
Try it Yourself »
Change the <body> of a document (overwrite all existing content):
document.body.innerHTML = «Some new HTML content»;
Try it Yourself »
More examples below.
В этой статье мы изучим методы JavaScript для поиска элементов в HTML-документе: querySelector
, querySelectorAll
, getElementById
и другие. Кроме них рассмотрим ещё следующие: matches
, contains
и closest
. Первые два из них могут быть полезны для выполнения различных проверок, а третий использоваться, когда нужно получить родительский элемент по CSS-селектору.
Методы для выбора HTML-элементов
Работа с веб-страницей так или иначе связана с манипулированием HTML-элементами. Но перед тем, как над ними выполнить некоторые действия (например, добавить стили
), их сначала нужно получить
.
Выбор элементов в основном выполняется с помощью этих методов:
Они позволяют выполнить поиск HTML-элементов . При этом querySelector
выбирает один элемент, а querySelectorAll
– все.
Кроме них имеются ещё:
Но они сейчас применяются довольно редко. В основном используется либо querySelector
, либо querySelectorAll
.
Методы getElement(s)By* для выбора HTML-элементов
Здесь мы рассмотрим методы, которые сейчас применяются довольно редко для поиска HTML-элементов. Но в некоторых случаях они могут быть очень полезны. Это:
-
getElementById
– получает один элемент поid
; -
getElementsByClassName
– позволяет найти все элементы с указанным классом или классами; -
getElementsByTagName
– выбирает элементы по тегу; -
getElementsByName
– получает все элементы с указанным значением атрибутаname
.
1. Метод getElementById
позволяет найти HTML-элемент на странице по значению id
:
<div id="comments">...</div>
...
<script> // получим HTMLElement и сохраним его в переменную elComments const elComments = document.getElementById('comments');
</script> В качестве результата getElementById
возвращает объект класса HTMLElement
или значение null
, если элемент не был найден. Этот метод имеется только у объекта document
.
Указывать значение id
необходимо с учётом регистра. Так например, document.getElementById('aside')
и document.getElementById('ASIDE')
ищут элементы с разным id
.
Обратите внимание, что в соответствии со стандартом в документе не может быть несколько тегов с одинаковым id
, так как значение идентификатора на странице должно быть уникальным.
Тем не менее, если вы допустили ошибку и в документе существуют несколько элементов с одинаковым id
, то метод getElementById
более вероятно вернёт первый элемент, который он встретит в DOM. Но на это полагаться нельзя, так как такое поведение не прописано в стандарте.
То, что делает getElementById
можно очень просто решить посредством querySelector
:
// получим элемент #title
const elTitle = document.getElementById('title');
// получим элемента #title, используя querySelector
const elTitleSame = document.querySelector('#nav'); Кстати, оба этих метода возвращают в качестве результата один и тот же результат. Это либо HTML-элемент (экземпляр класса HTMLElement
) или null
, если элемент не найден.
2. Метод getElementsByClassName
позволяет найти все элементы с заданным классом или классами. Его можно применить для поиска элементов как во всём документе, так и внутри указанного. В первом случае его нужно будет вызывать как метод объекта document
, а во втором – как метод соответствующего HTML-элемента:
// найдем элементы с классом control в документе
const elsControl = document.getElementsByClassName('control');
// выберем элементы внутри другого элемента, в данном случае внутри формы с id="myform"
const elsFormControl = document.forms.myform.getElementsByClassName('form-control'); В качестве результата он возвращает живую HTML-коллекцию найденных элементов
. Чем живая коллекция отличается от статической мы рассмотрим ниже.
Здесь мы сохранили найденные элементы в переменные elsControl
и elsFormControl
. В первой переменной будет находиться HTMLCollection
, содержащая элементы с классом control
. Во второй – набор элементов с классом form-control
, находящиеся в форме с id="myform"
. Для получения этой формы мы использовали document.forms.myform
.
Метод getElementsByClassName
позволяет искать элементы не только по одному классу, но и сразу по нескольким, которые должны присутствовать у элемента:
// выберем элементы .btn.btn-danger
const elsBtn = document.getElementsByClassName('btn btn-danger'); На querySelectorAll
этот пример решается так:
const elsBtn = document.querySelectorAll('.btn.btn-danger'); 3. Метод getElementsByTagName
предназначен для получения коллекции элементов по имени тега:
// найдем все <a> в документе
const anchors = document.getElementsByTagName('a');
// найдем все >li> внутри #list
const elsLi = document.getElementById('list').getElementsByTagName('li'); На первой строчке мы выбрали все <a>
в документе и присвоили полученную HTMLCollection
переменной anchors
. На второй – мы сначала получили #list
, а затем в нём нашли все <li>
.
Задачу по выбору элементов внутри другого элемента с помощью querySelectorAll
выполняется намного проще:
const elsLi = document.querySelectorAll('#list li'); Для выбора всех элементов можно использовать символ *
:
// выберем все элементы в <body>
const els = document.body.getElementsByTagName('*'); 4. В JavaScript getElementsByName
можно использовать для выбора элементов, имеющих определенное значение атрибута name
:
// получим все элементы с name="phone"
const elsPhone = document.getElementsByName('phone'); Через querySelectorAll
это выполняется так:
const elsPhone = document.querySelectorAll('[name="phone"]'); More Examples
Create a <p> element and append it to the document’s body:
const para = document.createElement(«p»);
const node = document.createTextNode(«This is a paragraph.»);
Try it Yourself »
Типы и имена DOM-узлов
Как мы уже знаем структурой DOM является . Оно состоит из связанных друг с другом узлов. Узлы бывают разных типов, в зависимости от того, чему соответствует этот узел в HTML. То есть при преобразовании HTML-текста в DOM, разные сущности в нём преобразуются в разные типы узлов.
Основную структуру DOM-дерева составляют именно узлы, образованные HTML-тегами.
Их называют или просто .
Узнать тип узла в DOM можно с помощью свойства nodeType
:
console.log(document.nodeType); // 9
console.log(document.body.nodeType); // 1 Это свойство возвращает число от 1 до 12, обозначающее тип узла.
-
1
– элемент (Node.ELEMENT_NODE
); -
2
– атрибут (Node.ATTRIBUTE_NODE
); -
3
– текстовый узел (Node.TEXT_NODE
); -
8
– комментарий (Node.COMMENT_NODE
); -
9
– document (Node.DOCUMENT_NODE
); -
10
– узел, содержащий тип документа (Node.DOCUMENT_TYPE_NODE
); -
11
– узел, представляющий фрагмент документаDocumentFragment
(Node.DOCUMENT_FRAGMENT_NODE
).
В скобках приведены константы класса Node.
Они обычно используются в коде, когда нужно проверить тип DOM-узла в JavaScript.
Их намного удобнее использовать, чем запоминать числовые коды:
console.log(document.body.nodeType === Node.DOCUMENT_NODE); // false
console.log(document.body.nodeType === Node.ELEMENT_NODE); // true Например, получим doctype
документа и узнаем его числовой код:
const doctype = document.doctype;
// это ещё один способ как можно получить doctype документа
const doctypeSame = document.childNodes[0];
// получим числовой код узла
console.log(doctype.nodeType); // 10
console.log(doctypeSame.nodeType); // 10 Теперь изучим свойство nodeName
. С его помощью мы можем узнать имя узла или тег, если узел является элементом:
console.log(document.body.nodeName); // "BODY"
console.log(document.doctype.nodeName) // "html"
console.log(document.nodeName); // #document" Свойство nodeName
для других узлов, не являющимися элементами возвращает различные значения:
- для текстовых узлов –
"#text"
; - для узлов-комментариев –
"#comment"
; - для
document
–"#document"
и так далее.
Получить имя тега элемента можно не только с помощью nodeName
,
но также посредством свойства tagName
.
tagName
запрограммирован в браузере как геттер, он содержится в prototype
класса Element
. nodeName
– это тоже геттер,
но находится он в другом месте, в prototype
класса Node
.
Поэтому свойство tagName
доступно только для узлов-элементов, и не доступно для других типов узлов.
Прочитать про объекты, прототипы и наследование можно в этой статье
.
В браузерах при разработке веб-приложений и сайтов имеется очень полезный инструмент .
Открыть в браузере Chrome его можно через меню или посредством комбинации клавиш:
- – Cmd + Shift + I
; - – Ctrl + Shift + I
или F12
; - – Ctrl + Shift + I
.
На вкладке вы можете исследовать DOM и CSS. При необходимости их можно изменять прямо здесь, и смотреть как будут выглядеть эти правки прямо на веб-странице.
Выбрать нужный элемент на веб-странице можно разными способами:
- кликнуть по нему правой кнопкой мыши и выбрать в открывшемся меню пункт «Inspect» или «Посмотреть код»;
- найти его в DOM, для поиска элемента дополнительно можно использовать окно поиска, которое можно вызвать с помощью комбинации клавиш Ctrl + F
; - нажать на значок и визуально выбрать нужный элемент.
После выбора узла мы можем обратиться к нему в консоли через $0
. При этом предыдущий выбранный узел будет доступен как $1
и так далее. Это можно использовать при изучении DOM и отладке сайта.
// тип узла
$0.nodeType // 8
// имя узла
$0.nodeName // "#comment"
// значение узла
$0.nodeValue // " Заголовок H1 " 
Свойство nodeValue
позволяет получить содержимое текстового узла или комментария. Для остальных узлов оно возвращает в качестве значения null
.
С помощью nodeValue
e мы можем также установить новое значение этому узлу:

Кроме nodeValue
нам также доступно свойство data
, с помощью которого мы можем выполнить аналогичные действия:

Получить и изменить содержимое элементов осуществляется с помощью других свойств, таких как textContent
и innerHTML
. Например, выведем значения которые возвращают эти свойства для элемента <ul>
:

Здесь мы видим \n
и пробелы. \n
– это перевод строки. Так как по факту, например, первый <li>
расположен не сразу после <ul>
, а перед ним имеется вот такой контент. Он при парсинге страницы будет преобразован браузером в текстовый узел DOM. Таким образом, первым дочерним узлом <ul>
будет именно этот тестовый узел, и только потом уже <li>
. \n
образовался из-за того что мы поставили Enter
, а четыре пробела – это то количество пробелов, которые мы установили перед тем как написали тег <li>
.

В DOM пробелы, переводы строк, знаки табуляции и другие символы расположенные между элементами образуют текстовые DOM-узлы.
Например, чтобы их не было в <ul>
, его разметка должна быть записана следующим образом:
<ul><li>Android</li><li>iOS</li></ul> При выборе DOM-элемента на вкладке будет отображаться весь CSS, применённый к этому элементу, в том числе будет отображены и дефолтные стили браузера. Правила можно редактировать, отключать с помощью чекбоксов и дописывать новые. Все изменения применяются сразу.

На вкладке мы можем посмотреть результирующие стили, примененные к элементу.

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

Return Value
Перебор коллекции HTML-элементов
Перебор NodeList
обычно осуществляется с помощью forEach
:
// получим все <p> на странице
const elsP = document.querySelectorAll('p');
// переберём выбранные элементы
elsP.forEach((el) => { // установим каждому элементу background-color="yellow" el.style.backgroundColor = 'yellow';
}); // получим все элементы p на странице
const elsP = document.querySelectorAll('p');
// for
for (let i = 0, length = elsP.length; i < length; i++) { elsP[i].style.backgroundColor = 'yellow';
}
// for...of
for (let el of elsP) { el.style.backgroundColor = 'yellow';
} Warning
Setting the body
property overwrites all elements in the document’s <body>
Browser Support
document.body
is a DOM Level 1 (1998) feature.
It is fully supported in all browsers:
Description
The body
property sets or returns a document’s <body> element.
GetElementsBy* и живые HTML-коллекции
В JavaScript getElementsByTagName
, getElementsByClassName
и getElementsByName
в отличие от других методов (например, querySelectorAll
) возвращают живую коллекцию HTML-элементов
(на английском live HTMLCollection
). То есть коллекцию содержимое которой автоматически обновляется при изменении DOM. Для наглядности рассмотрим следующий пример.
Например, на странице изначально имеется два <li>
. Выберем их с помощью getElementsByTagName
и сохраним полученную HTMLCollection
в переменную els
. Теперь с помощью els
мы можем получить эту коллекцию. Сейчас в ней два <li>
. Затем через 5 секунд, используя setTimeout
добавим ещё один <li>
. Если сейчас мы обратимся к переменной els
, то увидим, что в ней уже находятся три <li>
:
<ul> <li>One</li> <li>Two</li>
</ul>
<script>
// получим живую коллекцию <li>
const els = document.getElementsByTagName('li');
// выведем количество <li> в консоль
console.log(`Количество <li>: ${els.length}`); // 2
// через 5 секунд добавим ещё один <li>
setTimeout(() => { // вставим на страницу новый <li> document.querySelector('ul').insertAdjacentHTML('beforeend', '<li>Three</li>');
// выведем количество <li> в консоль console.log(`Количество <li>: ${els.length}`); // 3
}, 5000);
</script> 
Как вы видите, здесь полученная коллекция является живой, то есть она может автоматически измениться. В ней сначала было два <li>
. Но после того, как мы на страницу добавили ещё один подходящий элемент, в ней их стало уже три.
Если в коде приведённом выше заменить выбор элементов на querySelectorAll
, то мы увидим, что в ней находится статическая (не живая) коллекция элементов:
// получим статическую коллекцию
const els = document.querySelectorAll('li'); <li> 
Как вы видите количество элементов в коллекции не изменилось. Чтобы после изменения DOM получить актуальную коллекцию элементов, их нужно просто выбрать заново посредством querySelectorAll
:
<ul> <li>One</li> <li>Two</li>
</ul>
<script>
// получим статическую коллекцию <li>
let els = document.querySelectorAll('li');
// выведем количество <li> в консоль
console.log(`Количество <li>: ${els.length}`); // 2
// через 5 секунд добавим ещё один <li>
setTimeout(() => { // вставим на страницу новый <li> document.querySelector('ul').insertAdjacentHTML('beforeend', '<li>Three</li>'); // получим заново статическую коллекцию <li> els = document.querySelectorAll('li'); // выведем количество <li> в консоль console.log(`Количество <li>: ${els.length}`); // 3
}, 5000);
</script> Таким образом в JavaScript насчитывается 6 основных методов для выбора HTML-элементов на странице. По чему они ищут и что они возвращают приведено на следующем рисунке:

Экземпляры класса HTMLCollection
не имеют в прототипе метод forEach
. Поэтому если вы хотите использовать этот метод для перебора такой коллекции, её необходимо преобразовать в массив:
const items = document.getElementsByClassName('item');
[...items].forEach((el) => { console.log(el);
}); Классы DOM-узлов
Узлы в DOM являются или другими словами экземплярами определенных классов.
Например, DOM-элемент <body>
является экземпляром класса HTMLBodyElement
. В этом можно убедиться следующим образом:
document.body.constructor.name // HTMLBodyElement
// или так
document.body.toString() // [object HTMLBodyElement]
// или так
document.body instanceof HTMLBodyElement // true Таким образом, DOM-узлы в JavaScript являются обычными объектами
.
С некоторыми свойствами и методами этих объектов мы уже познакомились выше.
// например, установим свойству id значение wrapper
document.body.id = 'wrapper';
// получим тег элемента
document.body.tagName // "BODY" Например, если выбрать на странице ссылку и получить её класс, то мы увидим, что она является
экземпляром HTMLAnchorElement
, а не HTMLBodyElement
.
$0.constructor.name // HTMLAnchorElement Экземпляры HTMLAnchorElement
в отличие от HTMLBodyElement
имеют свои определённые свойства и методы, которых нет у <body>
.
В DOM разные элементы могут являются экземплярами разных классов. Но все они в качестве прототипа имеют объект HTMLElement.prototype
, то есть значение свойства prototype
класса HTMLElement
:

document.querySelector('body').__proto__ === HTMLBodyElement.prototype; // true
// при наличии элемента <a> на странице
document.querySelector('a').__proto__ === HTMLAnchorElement.prototype; // true
// при наличии элемента <div> на странице
document.querySelector('div').__proto__ === HTMLDivElement.prototype; // true Таким образом, HTMLElement
– это базовый класс, от которого наследуется другие классы, такие как HTMLBodyElement
, HTMLAnchorElement
, HTMLDivElement
и другие. Они в отличие от HTMLElement
используются для создания конкретных HTML-элементов.
Но если пойти дальше и рассмотреть класс HTMLElement
, то он наследуется от Element
.
Кстати, класс Element
является основой не только для HTMLElement
, но и других классов, например, предназначенных для XML и SVG:

document.querySelector('body').__proto__.__proto__.__proto__ === Element.prototype; // true
// при наличии элемента <svg> на странице
document.querySelector('svg').__proto__.__proto__.__proto__.__proto__ === Element.prototype; // true Ещё выше находится класс Node
. Он содержит общие свойства и методы, характерные для всех DOM-узлов.
При этом класс Node
не применяется непосредственно для создания объектов. Он применяется для организации наследования. От него наследуется Element
и CharacterData
. От CharacterData
в свою очередь наследуются классы Text
и Comment
, которую используются соответственно для создания текстовых узлов и комментариев.

Если пойти ещё выше, то увидим в цепочке прототипов объект EventTarget.prototype
. Класс EventTarget
– это корневой класс, благодаря которому все DOM-узлы поддерживают обработку событий. В EventTarget.prototype
содержатся такие методы, как, например, addEventListener
, dispatchEvent
и другие.
После EventTarget
идёт уже Object
. Object
– это класс, который является потомком для всех объектов, которые имеются в JavaScript.
Таким образом, каждый узел в DOM является экземпляром того или иного класса. Набор свойств и методов, который имеет тот или иной узел в DOM определяется не только его классом, но и результатом наследования. Пример наследования классов DOM-узлов приведен на следующей схеме:

Следующая тема: Перемещение по элементам и узлам DOM-дерева
.
Related Pages
HTML reference: HTML <body> tag
Syntax
Return the body property:
Set the body property:
document.body = newContent
QuerySelector
Метод querySelector
также как и querySelectorAll
выполняет поиск по . Но в отличие от него, он ищет только один HTML-элемент:
// ищем #title во всём документе
const elTitle = document.querySelector('#title');
// ищем footer в <body>
const elFooter = document.body.querySelector('footer'); На первой строчке мы выбираем HTML-элемент, имеющий в качестве id
значение title
. На второй мы ищем в <body>
HTML-элемент по тегу footer
.
В качестве результата этот метод возвращает найденный или null
, если он не был найден.
querySelector
всегда возвращает один HTML-элемент
, даже если под указанный CSS-селектор подходят несколько:
<ul id="list"> <li>First</li> <li>Second</li> <li>Third</li>
</ul>
<script> // выберем <li>, расположенный в #list const elFirst = document.querySelector('#list > li'); elFirst.style.backgroundColor = 'yellow';
</script> Задачу, которую решает querySelector
можно выполнить через querySelectorAll
:
const elFirst = document.querySelectorAll('#list > li')[0]; Но querySelector
в отличие от querySelectorAll
делает это намного быстрее, да и писать так проще. То есть querySelectorAll
не возвращает как querySelector
сразу же первый найденный элемент. Он сначала ищет все элементы, и только после того, как он это сделает, мы можем уже обратиться к первому HTML-элементу в этой коллекции.
Обычно перед тем, как выполнить какие-то действия с найденным HTML-элементом необходимо сначала проверить, а действительно ли он был найден
:
const elModal = document.querySelector('.modal');
// если элемент .modal найден, то ...
if (elModal) { // переключим у elModal класс show elModal.classList.toggle('show');
} Здесь мы сначала проверили существования HTML-элемента, и только потом выполнили над ним некоторые действия.
QuerySelectorAll
Метод querySelectorAll
применяется для выбора всех HTML-элементов
, подходящих под указанный CSS-селектор
. Он позволяет искать элементы как по всей странице, так и внутри определённого элемента:
// выберем элементы по классу item во всем документе
const items = document.querySelectorAll('.item');
// выберем .btn внутри #slider
const buttons = document.querySelector('#slider').querySelectorAll('.btn'); Здесь на первой строчке мы нашли все элементы с классом item
. На следующей строчке мы сначала выбрали элемент с id="slider"
, а затем в нём все HTML-элементы с классом btn
.
Метод querySelectorAll
как вы уже догадались принимает в качестве аргумента CSS-селектор в формате строки, который соответственно и определяет искомые элементы. В качестве результата querySelectorAll
возвращает объект класса NodeList
. Он содержит все найденные элементы:

Полученный набор представляет собой статическую коллекцию HTML-элементов. Статической она называется потому, что она не изменяется. Например, вы удалили элемент из HTML-документа, а в ней как был этот элемент, так он и остался. Чтобы обновить набор, querySelectorAll
нужно вызвать заново:

Узнать количество найденных элементов
можно с помощью свойства length
:
// выберем элементы с атрибутом type="submit"
const submits = document.querySelectorAll('[type="submit"]');
// получим количество найденных элементов
const countSubmits = submits.length; Обращение к определённому HTML-элементу коллекции выполняется также как к элементу массива
, то есть по индексу. Индексы начинаются с 0
:
// получим первый элемент
const elFirst = submits[0];
// получим второй элемент
const elSecond = submits[1]; Здесь в качестве результата мы получаем или undefined
, если элемента с таким индексом в наборе NodeList
нет.
Задачи
1. Узнать количество элементов с атрибутом data-toggle="modal"
на странице:
const count = document.querySelectorAll('[data-toggle="modal"]').length;
console.log(count); 2. Найти все элементы <a>
с классом nav
внутри элемента <ul>
:
const anchors = document.querySelectorAll('ul.nav a'); 3. Получить элемент по id
, значение которого равно pagetitle
:
var pagetitle = document.querySelector('#pagetitle'); 4. Выполнить поиск элемента по классу nav
:
var el = document.querySelector('.nav'); 5. Найти элемент <h3>
, находящийся в теге <div>
с классом comments
, который в свою очередь расположен в <main>
:
var header = document.querySelector('main div.comments h3'); 6. Имеется страница
. В ней следует выбрать:
- последний элемент с классом
article
, расположенный в<main>
( решение
); - все элементы
.section
, находящиеся в.aside
кроме 2 второго ( решение
); - элемент
<nav>
расположенный после<header>
( решение
).
Standard Properties and Events
The Body object also supports the standard properties
and events
.
Body Object
The Body object represents an HTML <body> element.
Access a Body Object
You can access a <body> element by using getElementsByTagName():
Tip:
You can also access a <body> element by using the
document.body
property.
Create a Body Object
You can create a <body> element by using the document.createElement() method:
var x = document.createElement(«BODY»);
Matches, closest и contains
В JavaScript имеются очень полезные методы:
-
matches
– позволяет проверить соответствует ли HTML-элемент указанному CSS-селектору; -
closest
– позволяет найти для HTML-элемента его ближайшего предка, подходящего под указанный CSS-селектор (поиск начинается с самого элемента); -
contains
– позволяет проверить содержит ли данный узел другой в качестве потомка (проверка начинается с самого этого узла).
1. Метод matches
ничего не выбирает, но он является очень полезным, так как позволяет проверить HTML-элемент на соответствие CSS-селектору. Он возвращает true
, если элемент ему соответствует, иначе false
.
// выберем HTML элемент, имеющий атрибут data-target="slider"
const elSlider = document.querySelector('[data-target="slider"]');
// проверим соответствует ли он CSS селектору 'div'
const result = element.matches('div'); Пример, в котором выберем все <li>
, расположенные внутри #questions
, а затем удалим те из них, которые соответствуют селектору .answered
:
// выберем все <li> в #questions
const els = document.querySelectorAll('#questions > li');
// переберём выбранные элементы
els.forEach((el) => { // если элемент соответствует селектору .answered, то ... if (el.matches('.answered')) { // удалим элемент el.remove(); }
}); В этом примере проверим каждый <li>
на соответствие селектору active
. Выведем в консоль каждый такой элемент:
<ul> <li>One</li> <li class="active">Two</li> <li>Three</li>
</ul>
<script> document.querySelectorAll('li').forEach((el) => { if (el.matches('.active')) { console.log(el); } }); // li.active
</script> Ранее, в «старых» браузерах данный метод имел название matchesSelector
, а также поддерживался с использованием префиксов. Если вам нужна поддержка таких браузеров, то можно использовать следующий полифилл:
if (!Element.prototype.matches) { Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector;
} 2. Метод closest
очень часто используется в коде. Он позволяет найти ближайшего предка, подходящего под указанный CSS-селектор. При этом поиск начинается с самого элемента, для которого данный метод вызывается. Если этот элемент будет ему соответствовать, то closest
вернёт его.
<div class="level-1"> <div class="level-2"> <div class="level-3"></div> </div>
</div>
<script> const el = document.querySelector('.level-3'); const elAncestor = el.closest('.level-1'); console.log(elAncestor);
</script> Здесь мы сначала выбираем HTML-элемент .level-3
и присваиваем его переменной el
. Далее мы пытаемся среди предков этого элемента включая его сам найти такой, который отвечает заданному CSS-селектору, в данном случае .level-1
.
Начинается поиск всегда с самого этого элемента. В данном случае он не подходит под указанный селектор. Следовательно, этот метод переходит к его родителю. Он тоже не отвечает этому CSS-селектору. Значит, closest
переходит дальше, то есть уже к его родителю. Этот элемент подходит под указанный селектор. Поэтому поиск прекращается и этот метод возвращает его в качестве результата.
Метод closest
возвращает null
, когда он дошёл бы конца иерархии и не нашёл элемент отвечающий указанному селектору. То есть, если такого элемента нет среди предков.
В этом примере найдем с помощью closest
для .active
его ближайшего родителя, отвечающего CSS-селектору #list > li
:
<ul id="list"> <li>One</li> <li> Two <ul> <li>Four</li> <li class="active">Five</li> </ul> </li> <li>Three</li>
</ul>
<script> const elActive = document.querySelector('.active'); const elClosest = elActive.closest('#list > li'); elClosest.style.backgroundColor = 'yellow';
</script> В JavaScript closest
очень часто используется в обработчиках событий
. Это связано с тем, чтобы события всплывают
и нам нужно, например, узнать кликнул ли пользователь в рамках какого-то элемента:
document.addEventListener('click', (e) => { if (e.closest.matches('.btn__action')) { // пользователь кликнул внутри .btn__action }
}); 3. Метод contains
позволяет проверить содержит ли некоторый узел другой в качестве потомка. При этом проверка начинается с самого этого узла, для которого этот метод вызывается. Если узел соответствует тому для которого мы вызываем данный метод или является его потомком, то contains
в качестве результата возвращает логическое значение true
. В противном случае false
:
<div id="div-1"> <div id="div-2"> <div id="div-3">...</div> </div>
</div>
<div id="div-4">...</div>
<script> const elDiv1 = document.querySelector('#div-1'); elDiv1.contains(elDiv1); // true const elDiv3 = document.querySelector('#div-3'); elDiv1.contains(elDiv3); // true const elDiv4 = document.querySelector('#div-4'); elDiv1.contains(elDiv4); // false
</script> Здесь выражение elDiv1.contains(elDiv1)
возвращает true
, так как проверка начинается с самого элемента. Это выражение elDiv1.contains(elDiv3)
тоже возвращает true
, так как elDiv3
находится внутри elDiv1
. А вот elDiv1.contains(elDiv4)
в качестве результата возвращает false
, так как elDiv4
не находится внутри elDiv1
.
В этом примере проверим с помощью contains
содержит ли <p>
другие узлы в качестве потомка:
<h1>Tag b</h1>
<p>This is <b>tag b</b>.</p>
<script> const elP = document.querySelector('p'); const elB = document.querySelector('b'); const textNode = elB.firstChild; const elH1 = document.querySelector('h1'); elP.contains(elP); // true elP.contains(elB); // true elP.contains(elH1); // false elP.contains(textNode); // true
</script> Метод contains
позволяет проверить является ли потомком не только узел-элемент, но и любой другой узел. Например, узнаем является ли потомком elDiv1
указанный текстовый узел:
const elDiv1 = document.querySelector('#div-1');
const textNode = document.querySelector('#div-3').firstChild;
elDiv1.contains(textNode); // true 
