DOM-коллекции
Как мы уже видели, childNodes
похож на массив. На самом деле это не массив, а коллекция – особый перебираемый объект-псевдомассив.
И есть два важных следствия из этого:
- Для перебора коллекции мы можем использовать
for..of
:
for (let node of document.body.childNodes) {
alert(node); // покажет все узлы из коллекции
}
Это работает, потому что коллекция является перебираемым объектом (есть требуемый для этого метод Symbol.iterator
).
- Методы массивов не будут работать, потому что коллекция – это не массив:
alert(document.body.childNodes.filter); // undefined (у коллекции нет метода filter!)
Первый пункт – это хорошо для нас. Второй – бывает неудобен, но можно пережить. Если нам хочется использовать именно методы массива, то мы можем создать настоящий массив из коллекции, используя Array.from
:
alert( Array.from(document.body.childNodes).filter ); // сделали массив
DOM-коллекции – только для чтения
DOM-коллекции, и даже более – все навигационные свойства, перечисленные в этой главе, доступны только для чтения.
Мы не можем заменить один дочерний узел на другой, просто написав childNodes[i] = ...
.
Для изменения DOM требуются другие методы. Мы увидим их в следующей главе.
DOM-коллекции живые
Почти все DOM-коллекции, за небольшим исключением, живые. Другими словами, они отражают текущее состояние DOM.
Если мы сохраним ссылку на elem.childNodes
и добавим/удалим узлы в DOM, то они появятся в сохранённой коллекции автоматически.
Не используйте цикл for..in
для перебора коллекций
Коллекции перебираются циклом for..of
. Некоторые начинающие разработчики пытаются использовать для этого цикл for..in
.
Не делайте так. Цикл for..in
перебирает все перечисляемые свойства. А у коллекций есть некоторые «лишние», редко используемые свойства, которые обычно нам не нужны:
<body>
<script>
// выводит 0, 1, length, item, values и другие свойства.
for (let prop in document.body.childNodes) alert(prop);
</script>
</body>
Соседи и родитель
Соседи – это узлы, у которых один и тот же родитель.
Например, здесь <head>
и <body>
соседи:
<html>
<head>...</head><body>...</body>
</html>
- говорят, что
<body>
– «следующий» или «правый» сосед<head>
- также можно сказать, что
<head>
«предыдущий» или «левый» сосед<body>
.
Следующий узел того же родителя (следующий сосед) – в свойстве nextSibling
, а предыдущий – в previousSibling
.
Родитель доступен через parentNode
.
Например:
// родителем <body> является <html>
alert( document.body.parentNode === document.documentElement ); // выведет true
// после <head> идёт <body>
alert( document.head.nextSibling ); // HTMLBodyElement
// перед <body> находится <head>
alert( document.body.previousSibling ); // HTMLHeadElement