DOM, elementler ve içerikleri ile her şeyi yapmamıza izin verir, ancak önce ilgili DOM nesnesine ulaşmamız gerekir.
DOM üzerindeki tüm işlemler document nesnesiyle başlar. Bu nesneden herhangi bir düğüme erişebiliriz.
DOM düğümleri arasında dolaşmaya izin veren bağlantıların bir görüntüsü:
Bunlara daha ayrıntılı değinelim.
Üstte: documentElement ve body
En üstteki ağaç düğümleri doğrudan document özellikleri olarak kullanılabilir:
<html>=document.documentElement- En üstteki belge düğümü
document.documentElement’tir. Bu,<html>etiketinin DOM düğümüdür. <body>=document.body- Yaygın olarak kullanılan başka bir DOM düğümü,
<body>elementidir –document.body. <head>=document.head<head>etiketidocument.headolarak mevcuttur.
document.body, null olabilir.Bir komut dosyası (script), çalışma anında mevcut olmayan bir öğeye erişemez.
Özellikle, bir komut dosyası <head> içindeyse, tarayıcı henüz okumadığı için document.body kullanılamaz.
Bu nedenle, aşağıdaki örnekte ilk alert null gösterir:
<html>
<head>
<script>
alert( "From HEAD: " + document.body ); // null, there's no <body> yet
</script>
</head>
<body>
<script>
alert( "From BODY: " + document.body ); // HTMLBodyElement, now it exists
</script>
</body>
</html>
null means “doesn’t exist”In the DOM, the null value means “doesn’t exist” or “no such node”.
Children: childNodes, firstChild, lastChild
There are two terms that we’ll use from now on:
- Child nodes (or children) – elements that are direct children. In other words, they are nested exactly in the given one. For instance,
<head>and<body>are children of<html>element. - Descendants – all elements that are nested in the given one, including children, their children and so on.
For instance, here <body> has children <div> and <ul> (and few blank text nodes):
<html>
<body>
<div>Begin</div>
<ul>
<li>
<b>Information</b>
</li>
</ul>
</body>
</html>
…And all descendants of <body> are not only direct children <div>, <ul> but also more deeply nested elements, such as <li> (a child of <ul>) and <b> (a child of <li>) – the entire subtree.
The childNodes collection provides access to all child nodes, including text nodes.
The example below shows children of document.body:
<html>
<body>
<div>Begin</div>
<ul>
<li>Information</li>
</ul>
<div>End</div>
<script>
for (let i = 0; i < document.body.childNodes.length; i++) {
alert( document.body.childNodes[i] ); // Text, DIV, Text, UL, ..., SCRIPT
}
</script>
...more stuff...
</body>
</html>
Please note an interesting detail here. If we run the example above, the last element shown is <script>. In fact, the document has more stuff below, but at the moment of the script execution the browser did not read it yet, so the script doesn’t see it.
Properties firstChild and lastChild give fast access to the first and last children.
They are just shorthands. If there exist child nodes, then the following is always true:
elem.childNodes[0] === elem.firstChild
elem.childNodes[elem.childNodes.length - 1] === elem.lastChild
There’s also a special function elem.hasChildNodes() to check whether there are any child nodes.
DOM collections
As we can see, childNodes looks like an array. But actually it’s not an array, but rather a collection – a special array-like iterable object.
There are two important consequences:
- We can use
for..ofto iterate over it:
for (let node of document.body.childNodes) {
alert(node); // shows all nodes from the collection
}
That’s because it’s iterable (provides the Symbol.iterator property, as required).
- Array methods won’t work, because it’s not an array:
alert(document.body.childNodes.filter); // undefined (there's no filter method!)
The first thing is nice. The second is tolerable, because we can use Array.from to create a “real” array from the collection, if we want array methods:
alert( Array.from(document.body.childNodes).filter ); // now it's there
DOM collections, and even more – all navigation properties listed in this chapter are read-only.
We can’t replace a child by something else by assigning childNodes[i] = ....
Changing DOM needs other methods. We will see them in the next chapter.
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.
for..in to loop over collectionsCollections are iterable using for..of. Sometimes people try to use for..in for that.
Please, don’t. The for..in loop iterates over all enumerable properties. And collections have some “extra” rarely used properties that we usually do not want to get: