About

Posted April 23, 2007
← Go to home page
← See all articles

Ads

Article

Optimizing JavaScript with DOM Access Objects

In my two years at FeedBurner, I’ve done a lot more JavaScript development than ever before. One of my favorite new techniques is creating DOM Access Objects to improve JavaScript performance and consolidate DOM access in your code.

A beneficial abstraction

For those of you who know what data access objects are, this should be a familiar technique. Here’s the gist: Rather than query the DOM (i.e. database) directly in code, abstract and isolate those queries.

According to Wikipedia:

The advantage of using data access objects is that [application logic] does not require direct knowledge of the final destination for the information it manipulates.

… and the same is true in JavaScript. You can change the way you do DOM access (from, say, Prototype’s Element methods to jQuery’s CSS-style selectors) without having to dig through your code to find every single place you used getElementsByClassName.

But there’s another advantage to DOM Access Objects in Javascript, and that is performance.

Removing redundant DOM access

One of the first “real-world” lessons I learned writing JavaScript was: DOM access is expensive.

So, whenever I’m writing JavaScript with non-trivial or repetitive DOM access, my first optimization is to “cache” DOM elements by assigning them to variables in code.

Assigning these to global variables works fine for small scripts, but I found a few advantages to constructing DOM Access Objects that include multiple element references:

  1. You can group related elements, then “initialize” (by doing all the DOM access at once) the object when necessary
  2. Since it’s an object, you can attach other related properties and methods (like an “initialize” method described in #1)
  3. Namespaces are good; they make your code easier to maintain and reduce conflicts with other JavaScript

(If you want to get really crazy, you can go to town with #2 and write custom accessors/mutators for all your elements. Just be careful not to overdo it.)

Example

Here’s a hypothetical example of a DOM Access Object in JavaScript (using jQuery):

var domAccessObject = {
  load: function() {
    this.outputs.load();
    this.inputs.load();
  },
  outputs: {
    load: function() {
      this.message = $("#message").get(0);
      this.errors = $("#input li.error").get();
    }
  },
  inputs: {
    load: function() {
      this.text = $("#input :text").get();
      this.submit = $("#input :submit").get(0);
    }
  }
};

When you need to use this object, you call domAccessObject.load(), which triggers all of the jQuery-powered DOM access. Then, if you want to update the “message,” for example, you can use domAccessObject.outputs.message.innerHTML.

There are even some arrays in there — you can iterate over domAccessObject.inputs.text, for example, to access all of the text input elements.

(The main performance gain here, in case it’s not clear, is in not having to do $("#input :text") every time you want to do something to the text inputs.)

Since this is an object, you can also do neat things like iterate recursively over it. For Headline Animator, I use this technique to copy “theme” values from a JSON object to form elements. It’s an 8-line recursive function. Rad.

Prior art?

I almost didn’t write this post because it seemed a bit… unoriginal. Dustin Diaz’s JSON for the masses is particularly similar. So take this with the usual disclaimer: This technique works for me, and I hope it works for you. YMMV.