Sep 28, 2011
Live vs. Static Node Lists
Posted in "development"
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:
<iframe style="width: 100%; height: 500px; border: 1px solid #ccc; padding: 3px;" src="http://jsfiddle.net/darcyclarke/sNL5f/3/embedded/"></iframe>
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.
<iframe style="width: 100%; height: 500px; border: 1px solid #ccc; padding: 3px;" src="http://jsfiddle.net/darcyclarke/e6Sa6/embedded/"></iframe>
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.