DOM позволяет нам делать что угодно с элементами и их содержимым, но для начала нужно получить соответствующий DOM-объект.
Все операции с DOM начинаются с объекта document. Это главная «точка входа» в DOM. Из него мы можем получить доступ к любому узлу.
Так выглядят основные ссылки, по которым можно переходить между узлами DOM:
Поговорим об этом подробнее.
Сверху: documentElement и body
Самые верхние элементы дерева доступны как свойства объекта document:<html> = document.documentElement Самый верхний узел документа: document.documentElement. В DOM он соответствует тегу <html>.<body> = document.body
Другой часто используемый DOM-узел – узел тега <body>: document.body.<head> = document.head. Тег <head> доступен как document.head.
Есть одна тонкость: document.body может быть равен null
Нельзя получить доступ к элементу, которого ещё не существует в момент выполнения скрипта.
В частности, если скрипт находится в <head>, document.body в нём недоступен, потому что браузер его ещё не прочитал.
Поэтому, в примере ниже первый alert выведет null:
<html>
<head>
<script>
alert( "Из HEAD: " + document.body ); // null, <body> ещё нет
</script>
</head>
<body>
<script>
alert( "Из BODY: " + document.body ); // HTMLBodyElement, теперь он есть
</script>
</body>
</html>
В мире DOM null означает «не существует»
В DOM значение null значит «не существует» или «нет такого узла».
Дети: childNodes, firstChild, lastChild
Здесь и далее мы будем использовать два принципиально разных термина:
- Дочерние узлы (или дети) – элементы, которые являются непосредственными детьми узла. Другими словами, элементы, которые лежат непосредственно внутри данного. Например,
<head>и<body>являются детьми элемента<html>. - Потомки – все элементы, которые лежат внутри данного, включая детей, их детей и т.д.
В примере ниже детьми тега <body> являются теги <div> и <ul> (и несколько пустых текстовых узлов):
<html>
<body>
<div>Начало</div>
<ul>
<li>
<b>Информация</b>
</li>
</ul>
</body>
</html>
…А потомки <body>– это и прямые дети <div>, <ul> и вложенные в них: <li> (потомок <ul>) и <b> (потомок <li>) – в общем, все элементы поддерева.
Коллекция childNodes содержит список всех детей, включая текстовые узлы.
Пример ниже последовательно выведет детей document.body:
<html>
<body>
<div>Начало</div>
<ul>
<li>Информация</li>
</ul>
<div>Конец</div>
<script>
for (let i = 0; i < document.body.childNodes.length; i++) {
alert( document.body.childNodes[i] ); // Text, DIV, Text, UL, ..., SCRIPT
}
</script>
...какой-то HTML-код...
</body>
</html>
Обратим внимание на маленькую деталь. Если запустить пример выше, то последним будет выведен элемент <script>. На самом деле, в документе есть ещё «какой-то HTML-код», но на момент выполнения скрипта браузер ещё до него не дошёл, поэтому скрипт не видит его.
Свойства firstChild и lastChild обеспечивают быстрый доступ к первому и последнему дочернему элементу.
Они, по сути, являются всего лишь сокращениями. Если у тега есть дочерние узлы, условие ниже всегда верно:
elem.childNodes[0] === elem.firstChild
elem.childNodes[elem.childNodes.length - 1] === elem.lastChild
Для проверки наличия дочерних узлов существует также специальная функция elem.hasChildNodes().