The Importance of a Good jQuery Selector

As a technical lead and working in a company that has had rapid expansion in the last six months or so, I have had the job of being a mentor to some of the new employees. I don’t think any of them had used jQuery before and so for every person that arrived, I needed to give a crash course on the subject. The jQuery selector is always one of the first things I describe and it is usually met with nods of understanding, as it is not a difficult concept to grasp when most developers are familiar with css and the DOM.

There have been two incidents recently however, that have made me realise that my crash course on jQuery selectors has been missing something vital. The first was when I found some time to explore the options of profiling some of our javascript code. When I first started this, the only option I could see was John Resig’s deep profiling script that injected the statistics at the bottom of the page. This had some limitations however, and I was very happy to open my news feeds soon after and find that he had added a couple of extra methods to FireUnit that enabled you to profile javascript function calls.

What I noticed straight away was that there were a lot of seemingly simple calls in our code that took a long time to execute. The reason for this was that the selectors were vague:

    $('.myclass').somefunction();

In order to find all the matches, even if there is only one, jQuery needs to traverse the entire DOM looking for any element that might have the matching class, and that takes time. By narrowing down the selector using, for instance, the type, jQuery can very quickly eliminate all other types. This speeds things up a lot.

The second incident was due to another ‘benefit’ of being a tech lead. I tend to get passed the most peculiar and hard to diagnose bugs. The bug in question was on a page that contained two autocomplete text boxes, one of which was part of a compound control. The bug manifested itself by not being able to select an item from the second autocomplete text box properly. I was handed the bug with the information that it seemed to happen only when you selected from the first autocomplete control first. Needless to say, there was a lot of poking around in the code of both the autocomplete and the compound control, which is particularly complex given the nature of the control.

Thanks to firebug‘s great console logging, I discovered that the variable that contained all the autocomplete list items seemed to be a combination of both controls. It was not too long before i discovered the code that caused the problem:

    listitems = $('.auto').children('li');

There was nothing mysterious going on at all, jQuery was asked to select all of list items in both controls, so it did.

What had happened in both of these incidents is that I had failed to mention the importance of an accurate selector in jQuery during my crash course. The new developers were blissfully unaware of the consequences of not specifying exactly which elements you want jQuery to select. What I had also failed to emphasise was another way of narrowing down and speeding up the jQuery selection – by use of the elements that you already have. In the case of the autocomplete, we already had a reference to the list itself, so it was simple:

   listitems = thelist.children('li');

This not only eliminated the cross-contamination of the two controls but seeded things up. So the rules to keep things fast and to save me headaches are simple:

  • Use a selector that very accurately matches the elements you require
  • Utilise references to elements you already have
 

2 thoughts on “The Importance of a Good jQuery Selector

  1. Ah yes, force them to use context, I had not thought of that. I like it as a solution to the problem. Would not like to think how much of our code it would break if I introduced the enforcement straight away. I may need to try and create the habit of using context before enforcing it with the code from Balazs. Great post.

Leave a Reply

Your email address will not be published. Required fields are marked *