(Side note: This post was published before on this blog, but since then I lost the database in a hosting issue, so this is rewritten. So if you think you recognise some of this, you may well do!)

While jQuery is a very popular library and does things very well, there are always improvements we can make. Such improvements on a small project may seem trivial, but to quote a popular supermarket, “every little helps”. So in this tutorial I’ll show you how we can improve and speed up how we select elements with jQuery.

Selecting Elements by Tag Name or Id

Using jQuery you can select elements using many methods, the post popular usage of selections is usually via an Id, a tag or a class:

$("#myElem"); //select using id
$(".myElem"); //select using class
$("a"); //select using tag

Native Javascript has a built in DOM method for selecting by Id or Tag, but not one for selecting elements by class. So, when you select an element via an Id, jQuery goes off and uses document.getElementById(), and similarly document.getElementsByTagName() for tag names. However, with there being no native class selector, jQuery has to do a lot more work (often looping through the entire DOM) to find the correct element(s). So therefore, whenever you can, you should avoid selecting by Class.

If you have to Select an Element by Class, provide a Context!

If there comes a time when you simply must select elements through a class selector, the last you can do for poor old jQuery is provide a context. This is often an overlooked yet very useful feature. By providing a context to jQuery, when it looks for elements by their class, it will only search within the context you provide.

UPDATE: A comment by Adam and also by Owen pointed out that this actually makes jQuery do more work. Some better solutions are to do this:

$("div.myElem"); //here jQuery can use getElementsByTagName() first to narrow down the search.

Or, if earlier on in your code you had cached a selector, this is also a good way:

$(".myElem", element); //where element has been cached already.

Thanks to Owen and Adam for making me aware of this. If you read Adam’s comment below, he also shows some benchmarking tests he did to back up his comment.

Avoid Parents!

If you can, avoid going back up to parent level. For example, the other day I saw this:

$("elem").find("p").css("display", "none").parent().find("h2").css("display", "none");

This is pretty poor. I asked why the code was done as such, and it turns out the user never knew that the .siblings() function could take a selector, meaning the code could be cut down:

$("elem").find("p").css("display", "none").siblings("h2").css("display", "none")

But this can still be improved:

$("elem").children("p, h2").css("display", "none");

Look at how much shorter that code is! By giving jQuery’s children() function two selectors, we cut down on how much work jQuery has to do. In the previous example, we selected the element, then found the paragraph, then changed the CSS of that, then searched for the h2 sibling, then changed the CSS of that! Now all we do is select our element, find the specific children, and apply our CSS change to both those elements at once. Much nicer, I think you will agree.

Cache those Selectors!

If you’ve selected an element you know you are going to have to refer to lots, save it! For example, this is pretty poor, jQuery will get upset if you do this:

$("#myElem").empty()
$("#myElem").css("border", "1px solid blue");

There are two better ways to do this. The first is to chain:

$("#myElem").empty().css("border", "1px solid blue");

And the second is to cache the selector:

var element = $("#myElem");
element.empty();
element.css("border", "1px solid blue")

I tend to save the element to a variable if I will need to use it later in the function. However, if I’m doing multiple things to an element at the same time, I just chain.

Hint – I’ve got into the habit of appending all variables that store the jQuery object with a dollar sign ($) to differentiate between those and normal variables. Like so:

var $myelement = $("#myelement");
var anumber = 5 * 5;

Now I can immediately see that $myelement relates to a jQuery selector, and anumber does not.

Caching also applies to the “this” keyword. Consider this loop:

$("div").each(function(i) {
$(this).addClass("myClass");
if($(this).hasClass("newClass") {
$(this).addClass("anotherClass");
}
});

While this might look all cosy, look how many times jQuery has to select the current element using $(this). This loop is much better:

$("div").each(function(i) {
var $this = $(this);
$this.addClass("myClass");
if($this.hasClass("newClass") {
$this.addClass("anotherClass");
}
});

Make use of andSelf()

Rarely used as much as it should, andSelf() is useful for chaining the previous selection. For example, take code such as this:

$("div").find("p").addClass("myClass").parent().addClass("myClass");

That would seem the only logical way to do things. But no! Check this out:

$("div").find("p").andSelf().addClass("myClass");

Which again, saves us repeating the addClass() function and generally is nicer to look at.

So that’s that, some easy ways to stripe down time your javascript takes to execute and generally make it nicer, cleaner, more DRY (Don’t repeat Yourself). Don’t you just love jQuery? Thanks for reading.

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Ping.fm Post to StumbleUpon