Wednesday, February 13, 2013

Why is the DOM Slow?

I was recently ask the following question via Twitter:

@therockncoder You once mentioned the DOM API as slow and jQuery as faster. Do you know what is causing the DOM to be slower?

Firstly, I would like to correct the question. While I did say that the DOM is slow, I didn't mean to imply that jQuery was fast, it can be but that isn't necessarily guaranteed. But why is the DOM slow?

There are a lot of reasons why the DOM is slow, so lets narrow our focus to just one reason. This reason is actually in the HTML specification. In section 1.1.1 The DOM Structure Model there is the following paragraph:

The DOM also specifies a NodeList interface to handle ordered lists of Nodes, such as the children of a Node, or the elements returned by the Element.getElementsByTagNameNS(namespaceURI, localName) method, and also a NamedNodeMap interface to handle unordered sets of nodes referenced by their name attribute, such as the attributes of an Element. NodeList and NamedNodeMap objects in the DOM are live; that is, changes to the underlying document structure are reflected in all relevant NodeList and NamedNodeMap objects. For example, if a DOM user gets a NodeListobject containing the children of an Element, then subsequently adds more children to that element (or removes children, or modifies them), those changes are automatically reflected in theNodeList, without further action on the user's part. Likewise, changes to a Node in the tree are reflected in all references to that Node in NodeList and NamedNodeMap objects.

The most relevant part of all of the text is that objects in the DOM are live. This means that anytime you change any part of the DOM, it is reflected in every DOM object almost magically. Needless updating every object takes time. And this is one of the reasons the DOM is slow. 

Need an example? In the example code, we get a count of the number of divs on the page. Initially there are two. Then we add one div to the page for each that exists. Our intention is to add two more divs for a total of four. But since we used document.getElementByTag to get the divs, we are holding onto a DOM object. Each time we add a div to the page, the length of divs increases and the increment counter, ndx, never exceeds the length of divs, and we are in an endless loop.

I borrowed this example from a tech talk given by Nicholas Zakas. The complete example program is on GitHub.