Once upon a time, all we needed to worry about was reducing Bytes and Requests and playing around with load order to make things faster. Nowadays, we are increasingly impacting one more major component in performance – CPU utilization. Using jQuery and other frameworks that make selecting nodes and DOM manipulation easy can have adverse affects if you’re not careful and follow some simple practices for reducing the work the browser has to do. Here is the jQuery performance rules for your website.

Today, after 7 years i have updated the article adding new 6 rules into it! (28.08.2016 UPDATED)

  1. Always Descend From an #id
  2. Use Tags Before Classes
  3. Cache jQuery Objects
  4. Harness the Power of Chaining
  5. Use Sub-queries
  6. Limit Direct DOM Manipulation
  7. Leverage Event Delegation (a.k.a. Bubbling)
  8. Eliminate Query Waste
  9. Defer to $(window).load
  10. Compress Your JS
  11. Learn the Library
  12. Avoid use of string concat(), Use join() for the long strings.
  13. Use Latest jQuery versions with CDN hosted files instead of older version.
  14. Use of For loop instead of jQuery $.each loop.
  15. Check if an Element Exists before doing operations on the DOM elements.
  16. Always use Return False in functions.
  17. Use of HTML5 Data Attributes.
  18.  Identify weight of the page.
  19. Keep your code DRY (Don’t Repeat Yourself)

1. Always Descend From an #id

The fastest selector in jQuery is the ID selector ($(‘#someid’)). This is because it maps directly to a native JavaScript method, getElementById().

Selecting Single Elements

<div id="content">
 <form method="post" action="/">
 <h2>Traffic Light</h2>
 <ul id="traffic_light">
 <li><input type="radio" class="on" name="light" value="red" /> Red</li>
 <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>
 <li><input type="radio" class="off" name="light" value="green" /> Green</li>
 </ul>
 <input class="button" id="traffic_button" type="submit" value="Go" />
 </form>
</div>

Selecting the button like this is slower: var traffic_button = $(‘#content .button’);
Instead, select the button directly: var traffic_button = $(‘#traffic_button’);

2) Selecting Multiple Elements

The second fastest selector in jQuery is the Tag selector ($(‘head’)). Again, this is because it maps to a native JavaScript method, getElementsByTagName()

<div id="content">
 <form method="post" action="/">
 <h2>Traffic Light</h2>
 <ul id="traffic_light">
 <li><input type="radio" class="on" name="light" value="red" /> Red</li>
 <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>
 <li><input type="radio" class="off" name="light" value="green" /> Green</li>
 </ul>
 <input class="button" id="traffic_button" type="submit" value="Go" />
 </form>
</div>

Always prefix a class with a tag name (and remember to descend from an ID):

var active_light = $(‘#traffic_light input.on’);
Note: The class selector is among the slowest selectors in jQuery; in IE it loops through the entire DOM. Avoid using it whenever possible. Never prefix an ID with a tag name. For example, this is slow because it will loop through all <div> elements looking for the ‘content’ ID:

var content = $(‘div#content’);
Along the same lines, it is redundant to descend from multiple IDs:

var traffic_light = $(‘#content #traffic_light’);

3. Cache jQuery Objects

Get in the habit of saving your jQuery objects to a variable (much like our examples above). For example, never (eeeehhhhver) do this:

$('#traffic_light input.on).bind('click', function(){...});
$('#traffic_light input.on).css('border', '3px dashed yellow');
$('#traffic_light input.on).css('background-color', 'orange');
$('#traffic_light input.on).fadeIn('slow');

Instead, first save the object to a local variable, and continue your operations:

var $active_light = $('#traffic_light input.on');
$active_light.bind('click', function(){...});
$active_light.css('border', '3px dashed yellow');
$active_light.css('background-color', 'orange');
$active_light.fadeIn('slow');

Tip: Since we want to remember that our local variable is a jQuery wrapped set, we are using $ as a prefix. Remember, never repeat a jQuery selection operation more than once in your application.

Bonus Tip – Storing jQuery results for later

If you intend to use the jQuery result object(s) in another part of your program, or should your function execute more than once, cache it in an object with a global scope. By defining a global container with jQuery results, we can reference them from within other functions:

// Define an object in the global scope (i.e. the window object)
window.$my =
{
 // Initialize all the queries you want to use more than once
 head : $('head'),
 traffic_light : $('#traffic_light'),
 traffic_button : $('#traffic_button')
};

function do_something()
{
 // Now you can reference the stored results and manipulate them
 var script = document.createElement('script');
 $my.head.append(script);

// When working inside functions, continue to save jQuery results
 // to your global container.
 $my.cool_results = $('#some_ul li');
 $my.other_results = $('#some_table td');

// Use the global functions as you would a normal jQuery result
 $my.other_results.css('border-color', 'red');
 $my.traffic_light.css('border-color', 'green');
}

4. Harness the Power of Chaining

The previous example can also be accomplished like this:

var $active_light = $('#traffic_light input.on');$active_light.bind('click', function(){...})
 .css('border', '3px dashed yellow')
 .css('background-color', 'orange')
 .fadeIn('slow');

This allows us to write less code, making our JavaScript more lightweight.

5. Use Sub-queries

jQuery allows us to run additional selector operations on a wrapped set. This reduces performance overhead on subsequent selections since we already grabbed and stored the parent object in a local variable.

<div id="content">
 <form method="post" action="/">
 <h2>Traffic Light</h2>
 <ul id="traffic_light">
 <li><input type="radio" class="on" name="light" value="red" /> Red</li>
 <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>
 <li><input type="radio" class="off" name="light" value="green" /> Green</li>
 </ul>
 <input class="button" id="traffic_button" type="submit" value="Go" />
 </form>
</div>

For example, we can leverage sub-queries to grab the active and inactive lights and cache them for later manipulation.

var $traffic_light = $('#traffic_light'),
 $active_light = $traffic_light.find('input.on'),
 $inactive_lights = $traffic_light.find('input.off');

Tip: You can declare multiple local variables by separating them with commas – save those bytes!

6. Limit Direct DOM Manipulation

The basic idea here is to create exactly what you need in memory, and then update the DOM. This is not a jQuery best practice, but a must for efficient JavaScript. Direct DOM manipulation is slow. For example, if you need to dynamically create a list of elements, do not do this:

var top_100_list = [...], // assume this has 100 unique strings
 $mylist = $('#mylist'); // jQuery selects our <ul> element

for (var i=0, l=top_100_list.length; i<l; i++)
{
 $mylist.append('<li>' + top_100_list[i] + '</li>');
}

Instead, we want to create the entire set of elements in a string before inserting into the DOM:

var top_100_list = [...], // assume this has 100 unique strings
 $mylist = $('#mylist'), // jQuery selects our <ul> element
 top_100_li = ""; // This will store our list items

for (var i=0, l=top_100_list.length; i<l; i++)
{
 top_100_li += '<li>' + top_100_list[i] + '</li>';
}
$mylist.html(top_100_li);

Even faster, we should always wrap many elements in a single parent node before insertion:

var top_100_list = [...], // assume this has 100 unique strings
 $mylist = $('#mylist'), // jQuery selects our <ul> element
 top_100_ul = '<ul id="#mylist">'; // This will store our entire unordered list

for (var i=0, l=top_100_list.length; i<l; i++)
{
 top_100_ul += '<li>' + top_100_list[i] + '</li>';
}
top_100_ul += '</ul>'; // Close our unordered list

$mylist.replaceWith(top_100_ul);

If you do the above and are still concerned about performance:

Give jQuery’s clone() method a try. This creates a copy of the node tree, which you can manipulate “off-line” and then insert back in when you are ready.
Use DOM DocumentFragments. As the creator of jQuery points out, they perform much better than direct DOM manipulation. The idea would be to create what you need (similar to what we did above with a string), and use the jQuery insert or replace methods.

7. Leverage Event Delegation (a.k.a. Bubbling)

Unless told otherwise, every event (e.g. click, mouseover, etc.) in JavaScript “bubbles” up the DOM tree to parent elements. This is incredibly useful when we want many elements (nodes) to call the same function. Instead of binding an event listener function to many nodes—very inefficient—you can bind it once to their parent, and have it figure out which node triggered the event. For example, say we are developing a large form with many inputs, and want to toggle a class name when selected. A binding like this is inefficient:

$('#myList li).bind('click', function(){
 $(this).addClass('clicked');
 // do stuff
});
Instead, we should listen for the click event at the parent level:

$('#myList).bind('click', function(e){
 var target = e.target, // e.target grabs the node that triggered the event.
 $target = $(target); // wraps the node in a jQuery object
 if (target.nodeName === 'LI') {
 $target.addClass('clicked');
 // do stuff
 }
});

The parent node acts as a dispatcher and can then do work based on what target element triggered the event. If you find yourself binding one event listener to many elements, you are doing something wrong (and slow).

8. Eliminate Query Waste

Although jQuery fails nicely if it does not find any matching elements, it still takes time to look for them. If you have one global JavaScript for your entire site, it may be tempting to throw every one of your jQuery functions into $(document).ready(function(){ // all my glorious code }). Don’t you dare. Only run functions that are applicable to the page. The most efficient way to do this is to use inline initialization functions so your template has full control over when and where JavaScript executes. For example, in your “article” page template, you would include the following code before the body close:

<script type=”text/javascript>
mylib.article.init();
</script>
</body>
If your page template includes any variety of modules that may or may not be on the page, or for visual reasons you need them to initialize sooner, you could place the initialization function immediately after the module.

<ul id="traffic_light">
 <li><input type="radio" class="on" name="light" value="red" /> Red</li>
 <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>
 <li><input type="radio" class="off" name="light" value="green" /> Green</li>
</ul>
<script type="text/javascript>
mylib.traffic_light.init();
</script>
Your Global JS library would look something like this:

var mylib =
{
 article_page :
 {
 init : function()
 {
 // Article page specific jQuery functions.
 }
 },
 traffic_light :
 {
 init : function()
 {
 // Traffic light specific jQuery functions.
 }
 }
}

9. Defer to $(window).load

There is a temptation among jQuery developers to hook everything into the $(document).ready pseudo event. After all, it is used in most examples you will find. Although $(document).ready is incredibly useful, it occurs during page render while objects are still downloading. If you notice your page stalling while loading, all those $(document).ready functions could be the reason why. You can reduce CPU utilization during the page load by binding your jQuery functions to the $(window).load event, which occurs after all objects called by the HTML (including <iframe> content) have downloaded.

$(window).load(function(){
 // jQuery functions to initialize after the page has loaded.
});

Superfluous functionality such as drag and drop, binding visual effects and animations, pre-fetching hidden images, etc., are all good candidates for this technique.

10. Compress Your JS

Okay, this isn’t jQuery related, but I had to include it. There is a tendency to make JavaScript functions and variables overly descriptive, which is essential for developers but irrelevant to users. No more excuses, it’s time to build JS compression into our workflows. Comment the heck out of your code, and run it through a compression tool before launching to production. Use YUICompressor to squeeze out wasteful bytes from your code. In our experience, it safely compresses JavaScript as small as it can possibly get without a CPU penalty (such as Base62 encoding with Packer). Tip: For maximum compression in YUICompressor, always declare your variables (e.g. var my_long_variable_name;).

11. Learn the Library

Print out this jQuery 1.3 cheat sheet, and make it a goal to eventually understand what each function does. If you find yourself repeating yourself repeating, there is probably an easier (and more efficient) way. jquery cheat sheet

12. Avoid use of string concat(), Use join() for the long strings.

Don’t use concat() function for the longer strings because join() speed up performance significantly by removing string manipulation in favor of arrays.

So Instead of the concat the string you can create the array and fill that array, later on you can join the elements together with the help of the join() function.

CONCAT() Method Example:

var list_items = "<li>Item 1</li>"; list_items += "<li>Item 2</li>";

list_items = list_items.concat("<li>Item 3</li>", "<li>Item 4</li>","<li>Item 5</li>"); $('#nav_list').html(list_items);

JOIN() Instead of CONCAT() and use of arrays for the same operations.

var list_items = [];

for (var i=0; i<=10; i++) { list_items[i] = '<li>Item '+i+'</li>';

}

$('#nav_list').html (list_items.join (''));

13. Use Latest jQuery versions with CDN hosted files instead of older version.

Always use of the latest jQuery version because each jquery version update have lot’s of fixes and have high performance as compare to the older versions.
Also, every new version comes with light-weight jQuery files as compared to older ones which results in less load time. Moreover, you can also use direct CDN (Content Delivery Network) to include jQuery in your application because CDN loads jQuery much faster.

Example of including latest version of jQuery using the CDN to save bandwidth and download faster:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>

14. Use of For loop instead of jQuery $.each loop.

The Native Javascript functions are much faster than any built-in helper’s functions provided by jQuery.
Lets take example of for loop, for loop is slightly faster in comparison with jQuery $.each method.
Example of $.each jQuery function:

$.each (js_array, function (i) {
js_array[i] = i;
});

Use of For Loop instead of above $.each

var js_array = new Array ();
for (var i=0; i<10000; i++) {
js_array[i] = i;
}

As per the above simple example we’re constructing the array using both methods but upon time measurement, it is observed that javascript native for loop is 10 times faster than $.each method of jQuery. This time difference increases in case of complex algorithms and methodologies.

15. Check if an Element Exists before doing operations on the DOM elements.

Always make sure to check for DOM element existence before doing any kind of operations with the same. By checking the existence, It will avoid any kind of errors / issues and It will also save your time.

Example:

if ($("#element").length) {
//The DOM element exists and do the operations.
}

16. Always use Return False in functions.

Do not forget to use “return false” in your functions as this increases performance of your jquery function by many times.
Let’s take very simple example of the jQuery click event to identify the things.

//jQuery click event to do some operations on the nav_item click.
$('#nav_item').click (function () {
    // stuff here
});

Use of below code instead of above,

Use of below code instead of above,
//jQuery click event to do some operations on the nav_item click.
$('#nav_item').click (function () {
    // stuff here
    return false;
});

17. Use of HTML5 Data Attributes

HTML 5 data attributes allows you to bind data to DOM elements without modifying the DOM. Before HTML5, it was very hard to manage arbitrary data without modifying the DOM.
To keep things work, you store the data in to pre-defined attributes (i.e rel or class attributes). So avoid storing data inside the DOM, and we can use HTML 5 Data attributes because it’s very easy and standard way to do so.
The important thing with HTML5 data attributes is that it also store serialize data in to the attributes which is very light-weight and thus we can access the data at higher rates.
Let’s take example:

<div id="demo" data-role="demo-page" data-value="111" data-options='{"name":"Walter John"}'></div>

To access the data attributes of this div, you would use code like the one below:

$("#demo").data("role");    // "demo-page"
$("#demo").data("value");    // 111
$("#demo").data("options").name;    // "Walter John";

18. Identify weight of the page.

We know that the more content on the page, browser takes more time to render the content. We can get the count of DOM elements to identify the same.
The website runs much faster with the less DOM elements; we can identify DOM element count by using the below code.

//Gives the count of DOM elements.
console.log( $(' ').length );

So If needed then you can optimize it by removing redundant and unnecessary wrapped elements to gain the page performance.

19. Keep your code DRY (Don’t Repeat Yourself)

If you are repeating the code for the similar kind of functionality, you’re doing something wrong and it’ll impact to the performance at the end. Let’s take example of Non-dry and dry code:

/* Non-Dry Code */
//Store some default data to the array and fill the data to inputs if the check-box will be checked.
var defaultData = {};
defaultData['name'] = "walter john";
defaultData['gender'] = "male";
//Code to do some operations while check-box is clicked.
$('.item_checkbox').click(function() {
    if(this.checked) {
        $('#input_name').val(defaultData.name);
        $('#input_gender').val(defaultData.gender);
    } else {
        $('#ineput_name').val('');
        $('#input_gender').val('');
    }
});
/* Use Dry Code instead of above repetitive code. */
$('.item_checkbox').click(function() {
    var checked = this.checked;
    $.each(['name','gender'],function(i,key) {
$('#input_'+key).val(checked ? defaultData[key] : '');
    });  
});