jQuery - Performance

jquery

Why should we use jQuery detach method?

It allows us to temporary remove the element from the DOM while we work on it if we need to perform multiple operations on the element or its children.

Why should we select elements by ID or tag name and avoid selecting elements by class name?

Select elements by ID or tag name. Avoid selecting elements by class name. Native Javascript contains two selectors: getElementById and getElementsbyTagName. You will notice there is no function to select elements by class. jQuery and most libraries do offer this function, and it’s not hard to write your own function to do it. However, due to it not existing natively, any custom function will be slower than using the two native functions above. So if you can avoid it, select elements by ID or by Tag Name over class where ever possible. Sometimes it is unavoidable of course, but if you can avoid it, do.

How can we cache result of DOM query?

Cache the result of DOM query. Save Selectors or chain them up.

$("div#elem").hide();
$("div#elem").css("width","200");
$("div#elem").show();

$("div#elem").hide().css("width","200").show();

var myElement = $("div#elem");
myElement.hide();
myElement.css("width","200");
myElement.show();

Why should we use find() instead of context?

Context sucks, use find.

// Extra Function Call
jQuery( 'div', context ).doSomething();

// Same functionality, minus the extra instance and function call
context.find('div').doSomething();

Why should we always use jQuery.data over the jQuery.fn.data method if you are getting/setting single key values?

// Wasted instance and two extra function calls
elem.click(function(){
    if ( jQuery(this).data('flag') == true ) {
        // do something...
    }
});

// Faster data process
elem.click(function(){
    if ( jQuery.data( this, 'flag' ) == true ) {
        // do something...
    }
});

In other words,

jQuery.data(DOMElement, 'key')

is faster than

jQuery(DOMElement).data('key')

Why is using .each considered as evil?

Actually, each is a pretty awesome utility function. The problem is that there is only one true reason to use each, and that is when a closure is needed for each item. If you are just looping through an array, then the callback function gets triggered on every iteration. So using an array of 25 items, the callback gets triggered 25 times. That can really add up depending on the size of your array.

Why should we provide extra contextual information when we have to query by class name?

$(".myElem");  // versus
$("div.myElem")

How can we avoid extra traversing?

The most common example of this is as follows:

$("elem").find("p").hide().parent.find("h2").hide();

What happens here is we find paragraphs within an element, hide it, then select those paragraph’s parent again, then find any h2 elements within that element, then hide it. What’s wrong? We start at the parent level, then find paragraphs within it, but then go back up to parent level to find the h2s within the parent. Why not use the siblings function?

$("elem").find("p).hide().siblings("h2").hide()

But this can be even further improved, as the find() function can take multiple selectors:

$("elem").find("p, h2").hide();

How can we 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.

How can we Use Stylesheets for Changing CSS on Many Elements?

If you're changing the CSS of more than 20 elements using .css(), consider adding a style tag to the page instead for a nearly 60% increase in speed.

// Fine for up to 20 elements, slow after that:
$( "a.swedberg" ).css( "color", "#0769ad" );

// Much faster:
$( "<style type=\"text/css\">a.swedberg { color: #0769ad }</style>")
    .appendTo( "head" );

Why should we avoid the Universal Selector?

Selections that specify or imply that a match could be found anywhere can be very slow.

$( ".buttons > *" ); // Extremely expensive.
$( ".buttons" ).children(); // Much better.

$( ":radio" ); // Implied universal selection.
$( "*:radio" ); // Same thing, explicit now.
$( "input:radio" ); // Much better.

How should we be more specific?

Be specific on the right-hand side of your selector, and less specific on the left.

// Unoptimized:
$( "div.data .gonzalez" );

// Optimized:
$( ".data td.gonzalez" );

Why should we use ID-based selectors?

// Fast:
$( "#container div.robotarm" );

// Super-fast:
$( "#container" ).find( "div.robotarm" );

With the first approach, jQuery queries the DOM using document.querySelectorAll(). With the second, jQuery uses document.getElementById(), which is faster, although the speed improvement may be diminished by the subsequent call to .find().

How can we avoid excessive specificity?

$( ".data table.attendees td.gonzalez" );

// Better: Drop the middle if possible.
$( ".data td.gonzalez" );

Why should we avoid selectors that include jQuery extensions?

When possible, avoid selectors that include jQuery extensions. These extensions cannot take advantage of the performance boost provided by the native querySelectorAll() DOM method and, therefore, require the use of the Sizzle selector engine provided by jQuery.

// Slower (the zero-based :even selector is a jQuery extension)
$( "#my-table tr:even" );

// Better, though not exactly equivalent
$( "#my-table tr:nth-child(odd)" );

Keep in mind that many jQuery extensions, including :even in the above example, do not have exact equivalents in the CSS specification. In some situations the convenience of these extensions could outweigh their performance cost.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License