I keep hearing people (Crockford in particular) saying the DOM is a terrible API, but not really justifying this statement. Apart from cross-browser inconsistencies, what are some reasons why the DOM is considered to be so bad?
Crockford has given an extensive presentation titled "An Inconvenient API: The Theory of the Dom" where he more or less explains his opinions on the DOM. It's longish (1h 18m), but as most Crockford's presentations it's quite enjoyable and educative.
Cross browsers inconsistencies seems to be his main concern, and I agree it's the single most annoying thing about the DOM. He identifies:
- Proprietary traps (browser and server traps),
- Rule breaking,
- Corporate warfare,
- Extreme time pressure
as the key issues behind the various inconsistencies, adding that presentation, session, or interactivity was never anticipated in the original vision of the web. Some examples of the inconsistencies include:
document.all, a Microsoft only feature,
- the fact that
idused to be interchangeable.
- the different functions on retrieving nodes:
and continues with a few more examples, mostly targeting traversing the DOM, memory leaks, and event trickling and bubbling. There is a summary slide, titled "The Cracks of DOM" that summarizes:
- The DOM buglist includes all of the bugs in the browser.
- The DOM buglist includes all of the bugs in all supported browsers.
- No DOM completely implements the standards.
- Much of the DOM is not described in any standard.
In short, it's a messy, messy API. It might seem like nitpicking, but you have to keep in mind that when you are developing for the web, you rarely get to pick the browser your customers will use. Having to test everything in at least two versions of each of the major browsers gets old very soon. An API is supposed to be consistent and the DOM was a victim of the browser wars, but it's getting better. It's still not as platform neutral as the W3C (and I think all of us) would like it to be, but browser vendors seem quite more eager to co-operate than they were five or ten years ago.
What's wrong with the DOM? Aside from Java-inspired syntax (which Crockford has touched on), nothing.
What's "wrong" applies partially to browser vendors; what's "wrong" applies to developers; what's "wrong" applies to ignorance.
So, where to begin?
Down the rabbit hole…
First off, browser vendors have fought competitively over decades to be the "best", "fastest", "easiest", etc. In the first decade (199x—2000), Microsoft ruled the roost. Internet Explorer introduced innovative ideas such as:
- exposing the browser's HTML parsing engine as
- easy textual manipulation with
- an event model (
*tachEvent) that was the blueprint for DOM Level 2 Events (
Each have contributed (for better and for worse) significantly to today's web development stack. Opera even went as far as to implement all three in version 7 (2003).
However, Netscape had its own DOM event model (
In 2000, it became the DOM Level 2 Events specification. Safari
1 (2003) implemented this model; Opera 7 (2003) also implemented
this model. As the ruins of Netscape became Mozilla, Firefox 1
(2004) inherited the model.
For the first section of the second decade (2000—2004), Microsoft
reigned supreme. Internet Explorer 6 (2001) was far and away the
best browser at the time. One of its competitors, Opera 6 (2001),
had yet to implement the DOM Level 1 Core (
createElement et al.)
Microsoft implemented it in Internet Explorer 4 (1997) before the
specification even became a recommendation (1998).
However, the second section of the second decade (2004—2010)
would prove disastrous for Microsoft. In 2003, Apple released
Safari 1.0; in 2004, Mozilla completed Firefox 1.0. Microsoft
was seemingly asleep on its throne atop the browser mountain.
Internet Explorer 7 was not released until 2006: a gap of five
years dating back to Internet Explorer 6's release date.
Unlike Internet Explorer versions 4 through 6, version 7
innovated little; DOM changes were minute. Nearly two-and-a-half
years later, Internet Explorer 8 was released. Microsoft had awoken
from its slumber and noticed the coalescence other browser vendors
had formed around numerous web standards. Unfortunately, too much
time had passed since Microsoft's last real innovation. A movement
had been created amongst browser vendors. New DOM features were to
be added in specification form to the W3C; Microsoft's ideas were
left in the past. Microsoft's event model (
eschewed for the DOM Level 2 Events model. Internet Explorer did
not implement the preceding model until version 9 (2011), which
became the DOM Level 3 Events model.
Microsoft's (DOM) follies can be summed up by the following points:
presence as a core feature of Windows, and the resulting OS-level security requirements;
reliance on ActiveX for client-side code;
innovation that tapered off curiously after version 6 (2001).
Secondly, developers bear a certain amount of blame. As the web has continued to take off, more and more people are "dabbling" in web development. This had led to a dilution in talent and work ethic. The problem, however, lies mainly with attitude. "Get it done quick" has taken precedence over "Get it done right." As a result, innumerable web pages are incompatible with various browsers. One of the leading causes of this incompatibility is a practice called "user agent sniffing". Though the practice is still in use today, it has been proved as both erroneous and harmful. Opera even went so far as to "freeze" the user agent version at "9.80" in version 10 (2009) and beyond. This was intended to prevent erroneous scripts from breaking. A much better practice called "feature testing" (albeit in mostly naïve form at the moment) has been adopted by developers.
Thirdly, my preferred point of blame is ignorance; ignorance in the fact that browser vendors did not work together nearly enough to create unified specifications; ignorance in the fact that Microsoft shunned users of other browsers; ignorance in the fact that developers are either too lazy or too myopic to bother researching browsers (especially those that are not en vogue.) There are many differences in APIs and implementations. Most can be avoided with a simplified-yet-defensive approach (reliance on DOM 0) along with copious amounts of both research and testing. Ignorance has led to the notion that Internet Explorer 6 is a blight upon the Earth (recall its spot on the browser throne mentioned earlier.)
Sadly, the DOM is just a misunderstood API. Many desire to throw stones (via FUD), but few desire to learn its intricacies. One result of this ignorance is the introduction of DOM "selectors". The DOM at heart is an API to manipulate document tree(s). Tree traversal should be used for complex problems given the form of a parsed document. With the introduction of the DOM Selectors API, a developer can now leverage the CSS traversal engine of the browser. This is quite convenient, but it conceals the true form of a document tree. With "selectors", element node retrieval is elementary. However, the DOM has eleven other node types specified. What of text nodes? Comment nodes? Document nodes? These are also nodes that are often desired while interacting with the DOM.
In short, take your time and read the various DOM specifications. Test code in as many browsers as possible. If Internet Explorer is perceived to be behaving oddly, consult MSDN. Most often, the behavior is documented.
(Historical anecdotes can and may be inaccurate; any inaccuracies are welcome to be raised.)
DOM is a terrible API
That is WRONG. DOM is NOT a terrible API.
First, remember that DOM is language agnostic. All major languages have implemented the API. This is because you just don't use it in browser, but everywhere you need to deal with XML.
Second, note that DOM does not define classes but interfaces. This has a very important implication: languages can implement it the way it suits their constructs and philosophy. This frees all the languages from having to be consistent in implementation with others.
Third, DOM is one of the two major ways to parse XML (other being SAX), and depending on your context, DOM can be very efficient.
What you are referring to is browser DOM. And, I agree that DOM "feels" bad in the browser. Part of the reason is browser incompatibilities. But, I disagree that they are the sole reason for DOM's bad reputation in the browser.
First, if you think about it, DOM is one of those areas where these incompatibilities are relatively easier to overcome. In comparison, events, for example are lot tricker and annoying to normalize.
Second, feature detection for DOM features is simpler than for other areas.
Third, DOM 3 is way better -- and today all browsers support most of it.
Certainly, incompatibilities are annoying, but when you get down to them, DOM is lot less irritating.
I also disagree with reasons like Proprietary traps, Corporate warfare, etc. being the reason for it.
Secondly, DOM has been designed for XML, and it has been adapted for HTML. Hence in the browser, we have exactly two DOMs -- HTML DOM and the XML DOM -- and they are incompatible.
Third, DOM traversal in the browser is not good. We don't have XPath for HTML DOM, so before CSS selector engines, it was really tedious to do traversals.
Finally, I think today, with the modern browsers, (and with older browsers slowly fading away) there is no reason DOM needs to be called bad. It's certainly going to get better in browser -- both the API and the implementation.
The DOM is great for what it was designed for: Documents
The DOM is basically just a tree representation of parsed HTML. It does a really good job for displaying documents and articles. For rich text and simple forms, it's a solid format that gets the job done well for a wide variety of use cases.
The DOM was not designed for apps
Adding, removing, and editing elements in the DOM can lead to all sorts of expensive calculations unless it is done very carefully. Knowing exactly where each of these are is difficult and the source of major performance issues, bugs, and other complications.
Two-way binding is also pretty easy to mess up, leading to bugs when you don't use a framework. You might forget one direction of the binding or read/write the data incorrectly. Some frameworks, such as React, avoid this entirely by replacing entire sections of the DOM each time something changes rather than modifying pieces of the DOM in-place.
Unless you are okay with shoehorning your app's data into a document-like data model, you're going to be spending time converting between data models and passing bits of data to and from inputs, and the performance of this is often invisible to the programmer.
A lot of friction and performance traps would melt away by rendering everything on a canvas rather than fighting with the browser on when it should be doing reflows and repaints. The cost to do your own rendering is all up-front, so this strategy will likely lead to less technical debt in the long run.