A little while ago, I was working on an application where I wanted to cache collections of elements to save on DOM traversals / improve performance. The problem with caching a collection of elements is that you’ll, in most cases, store a static node list. Thus, when new elements are introduced to the DOM, that match your selector, they won’t be included (unless you re-query the DOM).

JavaScript frameworks, like jQuery, return static arrays of elements by default. So, if you’re using a JavaScript framework, you’ll be well acquainted with either: re-querying the DOM, or using methods like .live() or .delegate(). That said, there are some native query methods you can use that will return live node lists.

document.getElementsByTagName(), document.getElementsByTagNameNS and document.getElementsByClassName() are the only options available that return “live” node lists. Looking at those methods, you may be discouraged, but don’t be. The returned is a live node list so all subsequent children of those elements will also be updated automatically. This means we can setup a live node list selector, that updates automatically, and then find the elements we’d like to use when ready.

Note: I’m not suggesting storing the whole body as a live node list but a more refined selection. Although, I guess, you could do that if you were so inclined.
var cache = document.getElementsByTagName('body');
vs.
var cache = document.getElementsByTagName('ul');

Here’s an example of a live node list in use:

So the key here is that we’ve moved away from re-querying the DOM and instead simply filtered our stored node list (which was the var test.ul = document.getElementsByTagName('ul');).

Another example I put together demonstrates the difference between a selection made with a JavaScript library like jQuery (and their Sizzle Selector Engine) verse a, rather basic, native selector method.

Of course, we need to factor in the robustness of a selector engine, such as Sizzle JS, compared to the simple document.getElementsByTagName(). The tradeoffs of each will come down to your individual scenario/use-case. Either way, it’s good to know how you’re interacting with the DOM and what options you have.

Note: Unfortunately, the latest query method, document.querySelectorAll(), was developed and standardized to return a static node list (booo!). Otherwise, this would be the ideal native method.

tags: / / / / / / / /

2 comments

  • Dave Stein

    Posted: Sep 29, 2011

    It’s a cool concept but I would think it opens up a lot of bug possibilities – most notably that your variable is self-updating. It would probably be better to just store your static array and then add it as you add elements manually.

    .live and .delegate are not necessarily comparable since they work off event bubbling and are not actually listening for a “live node”

  • Nick Lowman

    Posted: Oct 1, 2011

    There’s a good article by Zakas about static and live node lists here http://www.nczonline.net/blog/2010/09/28/why-is-getelementsbytagname-faster-that-queryselectorall/

"w3fools.com - because friends don't let friends use w3schools" ~ dan heberden
themify
Learning JavaScript