In Drupal we leverage jQuery on a regular basis. Wouldn’t it be great if we could make our jQuery selectors optimized and fast? The faster our JavaScript executes the faster our pages render. This is especially true due to older browsers with slower JavaScript engines and because one of the slowest types of operations even fast JavaScript engines deal with is DOM operations. Without further adieu, here are three tips for optimizing jQuery selector usage.
Use jQuery(context).find(selector)
All through Drupal, especially in `Drupal.behaviors`, we have code that starts our `$(selector, context)`. For the cases where context is a DOMElement, like it is for `Drupal.behaviors`, it is faster to use `$(context).find(selector)`.When a new jQuery object is created the constructor tries to figure out what was passed in. When context is a DOMElement jQuery transforms $(selector, context)
into $(context).find(selector)
. You can avoid much of the logic the constructor does including some string parsing by making this change yourself.
Use ID Optimization
Sizzle, the selector engine used by jQuery, is optimized for working with IDs when they are a single selector. That means we can optimize a selector like `$('#foo div.bar')` by transforming it into `$('#foo').find('div.bar')`.The original selector is optimized for the ID and this is overall faster because it takes advantage of how the selector engine works.
Think Right To Left
Most of the people who read this blog read left to right. But, selector engines search the DOM right to left. That means for a selector of `$('.foo .bar .baz')` all items containing `.baz` are found first, then among those results all of them that have parents with `.bar` are looked for. Then, it looks for the results that have `.foo` as a parent. This may seem odd but this is actually faster and how all the major browser selector engines work for CSS.If we understand how the selector engine works we can optimize what we search for. Maybe in the page all we needed was to look for $('.foo .baz')
. That would be faster. The idea is to be specific with the right part of the selector. The parts to the left of that should be as limited as possible to get to your matches.
This also means that selector searches like $('.foo :radio')
are actually like $('.foo *:radio')
. This checks every element in the page to see if its a radio and then refine from there. This is slow. $('.foo input:radio')
is faster because it only searches for input types.
These are just three tips among many that can help make out code faster. I you want to learn more a great place to start is with the jQuery source (http://bit.ly/jqsource), by reading the API documentation, or digging into Sizzle.