Don't be DOM with your DOM

Every developer who knows jQuery has written code like that looks like the following.

[gist id=b15d32c6780ef3170a1b]

Browsers are sophisticated creatures, and here we have tried valiantly to slow them down. Let’s examine what we have just asked them to do and how we can work with our friends, the Browsers, instead of against them.

Problem No. 1: DOM Querying.

The example code sets the expectation that you are handing jQuery a reference to a DOM node already. If this were true you could avoid the overhead of the selector engine (in the case of jQuery, this would be Sizzle) resolving your selector.

However, this code would be equally valid passing in a selector like '#main #tableview .data-table:nth-child(2)'. This would mean that each call to jQuery would need to perform that entire lookup again.

This is why caching your selectors is so valuable. The expense of selector matching would go from a minimum of three calls per scroll event in the above example to one.

Problem No. 2: Unnecessary Object Creation.

Everytime you call jQuery(element), you are creating a new jQuery object. In many traditional websites, this overhead would hardly be noticable. It’s very likely that no one will ever notice your lack of stewardship over memory management.

However, in a single page webapp, game, or other high performance scenario, these memory issues will compound. As noted in the solution to DOM Querying, you’ve also just reduced the number of objects floating in memory from three or more per scroll event to one. Total.

The garbage collector thanks you one thousand thanks.

Problem No. 3: Reflow. Repaint.

Reflow and repaint are browser operations that handle calculating layout and drawing. The depth of this topic is far beyond the scope this article, so I highly recommend “How Browsers Work” by Tali Garsiel on html5rocks. Also, Paul Irish has an amazing roundup of resources .

But what does repaint and reflow have to do with grabbing some elements and listening for some scroll event?

You have the power to trigger or not to trigger these events. There are a number of attributes that simply getting them will cause the browser to reflow. Tony Gentilcore has been even kind enough to provide a list concerning webkit. offsetWidth/offsetHeight, though, are two that will trigger reflow everytime. There is a reason jQuery neatly packages them both up nicely for us when we call .offset().

We triggered reflow not once, but twice, when we only needed to do so once. The browser does not like us very much right now.

By batching all of your reflow methods together, and then drawing later, we can greatly improve the performance of our webapps.

Wrapping up

None of these issues are enough to break the horse's back by their lonesome. Though, compounding these issues with the experience you are trying to build can quickly add up. (Who remembers the Twitter scrolling performance woes of yesteryear?)

I hope that by knowing a little bit more about what work you are asking the browsers powering your work to do, you are better equipped to make informed decisions.