Why DOM Suck

By Xah Lee. Date: . Last updated: .

DOM is really really weird.

whenever there's a weird tech, there's 2 possibilities. ① you don't understand it. ② it is badly designed.

in my experience of weird tech, Linden Scripting Lang, AutoHotkey, after years, realized the problem isn't me, it's it. Oh, count unix in.

DOM is weird in all sorts of ways, not just 1 way. Here's a incomplete list of the problems.

Nesting and Code Sequence Order Mismatch

Here is typical code of JavaScript and DOM, for creating a SVG graphics of a rectangle and text.

// create svg element
const svg1 = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg1. setAttribute ("width", "100" );
svg1. setAttribute ("height", "100" );

// create a shape
const cir1 = document.createElementNS("http://www.w3.org/2000/svg", "circle");
cir1.setAttribute("cx", 0 );
cir1.setAttribute("cy", 0 );
cir1.setAttribute("r", 50);

// attach the shape to svg
svg1 . appendChild ( cir1 );

// attach the svg to a element on page
document.getElementById ('x77738'). appendChild ( svg1 );

There are 2 major problems:

Notice the long url string in document.createElementNS("http://www.w3.org/2000/svg", "svg"). What were they thinking?

insert into tree

Suppose you have a tree, and you want to append a child.

So, you do this:


However, if the newNode you are appending is a element that exist in the document, that node will be removed. So, it's rather like “removeThenAppend()”.

Now, suppose you want to remove all children. Simple, you might think node.removeAllChildren() will do. However, there is no such function. You have to do a loop to remove each child.

while (node.firstChild) { node.removeChild(node.firstChild); }

alternatively, you use this invented by Microsoft:

node.innerHTML = '';

Note that, although this is quite convenient, but is odd, because it is inconsistent with the manipulating tree paradigm.

And strange thing is, this version is slower than the loop to keep removing child.

Insert Before

let's say you want to insert a node. You think:

insertBefore(newNode, existingNode)

or in OOP's style of notation:


but the actual API is:

ParentOfExistingNode.insertBefore(newNode, existingNode)

Note that, you actually have to get the parent of existing node to use it.

So, the actual code is:

existingNode.parentNode.insertBefore(newNode, existingNode)

For a API that manipulate trees, you'd think there's insertAfter() too. But not!

2018-04-10 Note, this problem has been fixed. [JavaScript: insertAdjacentElement]

Live Object

It's strange that some DOM function returns a live object.

For example, document.getElementsByClassName() returns a live NodeList or HTMLCollection.

Live object means, the result is some kinda reference to the thing, not a copy.

However, not all DOM methods that retrieve elements are live. Some returns a “copy”.

Live object is strange to work with. For example, if you try to go thru the list by a loop checking for length, and add items, it'll be a infinite loop. Because, when you add item, the length also increases.

[see DOM: Live Object]

JavaScript in Depth