A hitch hikers guide on how to improve jQuery performance

I see all to often the simple mistakes developers make when coding with jQuery.

Hopefully these tips will appear simple to you and thats because they ARE. These basic changes to your coding habits will have drastic performance improvements to your jQuery.

Use the latest version of jQuery

If you’re too lazy to read past the first tip then this is for you (mr lazy developer). 

Simply updating your jQuery to the latest available version can improve the performance of your website without changing a single line of code. jQuery is constantly being tweaked and refactored to improve its performance. For example have a look at the following graph of the performance boost for the attr() method from jQuery 1.5.2 to 1.6

jQuery attr() performance

Just remember to thoroughly test your code in a staging environment when upgrading jQuery and read the docs to see what might have been deprecated.

Use a CDN (Content Delivery Network)

Take full advantage of frameworks that are more than likely to be already cached client side. The more developers that use it, the faster all our sites load. I like to use googles jQuery CDN with a fallback like so:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script>
!window.jQuery && document.write(unescape('%3Cscript src="/javascript/libs/jquery-1.6.1.min.js"%3E%3C/script%3E'))
</script>

Visit http://code.google.com/apis/libraries/devguide.html for the latest jQuery location and usage.

Use smarter fast selectors

Selecting elements by id is the fastest method and uses the native javascript method getElementdById()
Selecting elements by tag is the 2nd fastest method and uses the native javascript method getElementByTagName()
Selecting elements by class is the slowest method and uses the native javascript method getElementByClass()

Always descend from the closest id in your selectors.
If you need to use a class selector, at least add a tag in front when possible. $(‘span.btn’) is faster than $(‘.btn’)

Eliminate query waste

jQuery executes on a liner thread (except for when using async stuff), it basically means it can only interperate one line of code or function at a time before moving to the next. I see the often mistake of developers dumping all their code into the document ready callback. You should never do this, its is more ideal to only run code/functions that are applicable to the page you’re viewing.

The best way to do this is break your code into separated class functions. Then initialise the code from inline scripts as they are needed.

Javascript

var myCustomClass= {
	init: function(){
		$(document).ready(function(){
			//code
		});
	}
};

Html

<script> myCustomClass.init(); </script>

The DOM is not a database

Create what you need in memory then update the DOM at the latest moment. Direct DOM manipulation is expensive. An example of this would be to build html into a string variable and only append when its ready.

Good (fast)

var htmlString;
for (i=0;i<100;i++){
	htmlString += "<li>Another list item</li>";
}

//All finished so lets inject into dom
$('ul').append(htmlString);

Bad (Slow)

for(i=0;i<100;i++){
	$('ul').append('<li>another list item</li>');
}

Cache your jQuery DOM elements. It’s a no brainer!

Querying the DOM for your elements is an resource expensive task. Its more ideal to save the element into a variable instance. Its also good practice to prefix your variable names with the dollor ($) sign as its a good indication the variable is a jQuery DOM element.

/* Lets save a list with the id 'aList' into memory */
var $myList = $('#aList');

/* Now that its cached into a instance variable we can 'cheaply' query it multiple times */
var listHeight = $myList.height();
$myList.children('li').eq(1).hide();
$myList.fadeOut(700);
//etc..

Use .delegate() it rocks!

Are you still using the old school hover() functions or maybe you have moved onto bind() or live(). The delegate() method was added to jQuery 1.4 and i was a huge fan instantly. There is certainly no shortage of event listner methods to choose from so here is why i recommend you start using .delegate()

  • It forces you to specify a context which gives you a performance head start.
  • It dosnt wait for your event to bubble all the way up the DOM.
  • It works for future elements. (eg. when using append/ajax)

For example, this is how I would typically use delegate for a hover effect on a list of items.

$('ul').delegate('li', 'mouseenter mouseleave', function(e){
	if(e.type == 'mouseenter'){
		//Mouse over code
	}
	else
	{
		//Mouse out code
	}
});

Utilise chaining properly

The one thing i love about jQuery is the ability to chain multiple method calls together. For example this is commonly used to switch states with a class

$('element').removeClass('active').addClass('de-activated')

Pretty straigt forward right. But jQuery chaining can go so much more eleberate than that, and the beautiful thing about it is we cut right down on our selector calls.

$('element')
	.removeClass('active')
	.find('div')
	.css({background:'#000'})
	.end()
	.append('<span> a new span </span>')
	.animate({left: 400}, 'slow');

Its common practice to write chaining methods on individual lines when there are lots of them. This helps with readability and remains valid javascript.

Use .empty() not .html(“”) to clear elements

If you empty a div or list by making its html equal an empty string, this can actually cause a memory leak for any events assigned to child DOM elements. The jQuery docs says:

To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.

Memory leaks can become a particular problem with devices such as phones. So always be safe and use .empty()

See more
Tagged with jquery, javascript, performance,
Posted at 6:37 PM 17 September 2011

What's on your mind...

Design by Funkytional