10 Advanced jQuery Performance Tuning Tips

There were a lot of good speakers at today’s jQuery Summit, but Paul Irish‘s talk on jQuery Anti-Patterns for Performance & Compression was my stand-out favorite. Covering a number of advanced jQuery performance optimization techniques, this speech put my knowledge of jQuery optimization to shame. Before Paul’s talk my understanding of jQuery performance tuning was fairly simplistic:
  1. Optimize selectors to descend from an id if possible.
  2. Use tag names when selecting classes and don’t use an excessive number of selectors.
  3. Define variables instead of selecting the same object repeatedly.
  4. Optimize your code replacing repetition with object oriented functions.
But the information Paul presented blew all that out of the water. Here are 10 jQuery performance rules I gathered from his presentation:

1. Optimize selectors for Sizzle’s ‘right to left’ model

As of version 1.3, jQuery has been using the Sizzle Javascript Selector Library which works a bit differently from the selector engine used in the past. Namely it uses a ‘right to left’ model rather than a ‘left to right’, which means that given a selector string such as $('div.class span.class2') the engine starts the search on the right using the most specific selector (the span.class2) and then checks each ancestor against div.class rather than starting on the left and checking descendants. But what does that mean for you? Make sure that your right-most selector is really specific and any selectors on the left are more broad. For instance use:
$('.class span.class2')
rather than:
$('div.class .class2')
And of course descending from an #id is still always best:
$('#id div.class')

2. Use live() not click()

jQuery’s new event handler live() is a much faster alternative to click(). It comes with an additional benefit that I am extremely excited about: the selector works even with dynamic content, meaning no more reattaching click events every time you change a piece of content. Live is faster and better for all click events and most other jQuery event handling, however stay away from it for tracking onmouseover or onsubmit.

3. Pull elements off of the DOM while you play with them

Let’s say you have a form that you want to append a series of inputs to. Normally you might do this:
var theForm = $('#myForm'); inputArr.each(function() { theForm.append(this); }); 
However it’s better to pull the form element off of the DOM while you play around with it:
var theForm = $('#myForm'); var formParent = theForm.parent(); theForm.remove(); inputArr.each(function() { theForm.append(this); }); formParent.append(theForm); 

4. Use find() rather than context

With jQuery selectors, context is good for performance, but find() is better. So instead of using context like this:
var panels = $('#content').find('div.panel');
It is better to use find():
var panels = $('#content').find('div.panel'); 
More info on context

5. Use HTML 5

HTML 5 means more tags: <section><header><footer>, etc. More tags mean that there are less items that share a given tag name, which translates into better selector performance.

6. Append style tags when styling 15 or more elements

When styling a few elements it is best to simply use jQuery's css() method, however when styling 15 or more elements it is more efficient to append a style tag to the DOM:
$('')
.appendTo('head');

7. Test selectors using Google Page Speed

The CSS selector optimization rules used by FireBug's Page Speed addon also apply to jQuery. If you want to test how well your selector is optimized, apply it with CSS and see if any selectors are flagged by Page Speed.

8. Use object detection even if jQuery doesn't throw an error

It's great that jQuery methods don't throw a ton of errors at your users, but that doesn't mean that as a developer you should just rely on that. Even though it won't throw an error, jQuery will have to execute a number of useless functions before determining that an object doesn't exist. So use a quick object detection before calling any methods on a jQuery object that may or may not exist.

9. Use direct functions rather than their convenience counterparts

If you look at the jQuery core you'll notice a variety of functions are just convenience methods for calling other functions, for instance if you call getJSON() it calls get()which calls ajax(). You can cut this extra work out of the loop by referencing the direct function ajax().

10. Learn the lesser known methods

With a vast and evolving library like jQuery it can be hard to keep on top of all the methods but it is still very important. Some methods Paul pointed out specifically aremap()slice()stop()queue()dequeue()prevAll()pushStack() andinArray(). Learning the variety of methods in your toolkit will help you to better use this library and write more concise code. The worst thing you can do is write a custom function for something that already exists in the jQuery core: besides bloating your Javascript, it would take a lot of effort to write code that is optimized as well as it is by the elite and enormous group of developers who work on and debug the jQuery core.
blog comments powered by Disqus