- There’s a “root” object called
window
. It has two roles:
- It is a global object for JavaScript code.
- It represents the “browser window” and provides methods to control it.
- The document object gives access to the page content.
- Browser Object Model (BOM) are additional objects provided by the browser (host environment) to work with everything except the document.
- According to DOM, every HTML-tag is an object.
- Nested tags are called “children” of the enclosing one.
- The text inside a tag it is an object as well.
- Tags are called element nodes (or just elements).
- Nested tags become children of the enclosing ones.
- As a result we have a tree of elements: <html> is at the root, then <head> and <body> are its children, etc.
- The text inside elements forms text nodes, labelled as #text.
- A text node contains only a string.
- It may not have children and is always a leaf of the tree.
- All operations on the DOM start with the document object.
- From it we can access any node.
- In the DOM world null means “doesn’t exist”.
- A script cannot access an element that doesn’t exist at the moment of running.
- In particular, if a script is inside
<head>
, then document.body
is unavailable, because the browser did not read it yet.
- The
childNodes
collection provides access to all child nodes, including text nodes.
- Properties
firstChild
and lastChild
give fast access to the first and last children.
- There’s also a special function
elem.hasChildNodes()
to check whether there are any child nodes.
for (let i = 0; i < document.body.childNodes.length; i++) {
console.log(document.body.childNodes[i]);
}
let elem = document.getElementById('MyId');
console.log(elem.childNodes[0] === elem.firstChild);
console.log(elem.childNodes[elem.childNodes.length - 1] === elem.lastChild);
childNodes
looks like an array but actually it’s not an array, but rather a collection – a special array-like iterable object.
- We can use
for..of
to iterate over it:
- That’s because it’s iterable (provides the
Symbol.iterator
property, as required).
- Array methods won’t work, because it’s not an array.
- We can use
Array.from
to create a “real” array from the collection, if we want array methods.
- DOM collections, and even more – all navigation properties are read-only.
- We can’t replace a child by something else by assigning
childNodes[i] = ...
.
- Almost all DOM collections with minor exceptions are live.
- In other words, they reflect the current state of DOM.
- If we keep a reference to
elem.childNodes
, and add/remove nodes into DOM, then they appear in the collection automatically.
Siblings and the Parent
// parent of <body> is <html>
alert(document.body.parentNode === document.documentElement); // true
// after <head> goes <body>
alert(document.head.nextSibling); // HTMLBodyElement
// before <body> goes <head>
alert(document.body.previousSibling); // HTMLHeadElement
Element-only Navigation
- Navigation properties listed above refer to all nodes.
- For instance, in
childNodes
we can see both text nodes, element nodes, and even comment nodes if there exist.
- The links are similar to those given above, just with
Element
word inside:
children
: only those children that are element nodes.
firstElementChild
, lastElementChild
: first and last element children.
previousElementSibling
, nextElementSibling
: neighbour elements.
parentElement
: the parent element.
- The
parentElement
property returns the “element” parent, while parentNode
returns “any node” parent.
- These properties are usually the same: they both get the parent.
- With the one exception of
document.documentElement
:
alert( document.documentElement.parentNode ); // document
alert( document.documentElement.parentElement ); // null
- The
documentElement
(<html>
) is the root node.
- Formally, it has
document
as its parent.
- But
document
is not an element node, so parentNode
returns it and parentElement
does not.