Why Performance? Best practices are very important Don’t follow them and browsers end up having to do more work More work = more memory usage = slower apps..and you don’t want that.
Tip 1: Stay up to date! ALWAYS use the latest version of jQuery core Performance improvements and bug fixes are usually made between each version Older versions (eg. 1.4.2) won’t offer these instant benefits
Tip 2: Know Your Selectors All selectors are NOT created equally Fastest to slowest selectors are: ◦ The ID Selectors (“#AnElementWithID”) ◦ Element selectors (“form”, “input”, etc.) ◦ Class selectors (“.someClass”) ◦ Pseudo & Attribute selectors (“:visible, :hidden, [attribute=value] etc.”) ID and element are fastest as backed by native DOM operations.
Pseudo-selectors: powerful but slow :hidden (above) is powerful but must be run against all the elements in your search space Pseudo/Attrib selectors have no browser-based call to take advantage of if ( jQuery.expr && jQuery.expr.filters ) { jQuery.expr.filters.hidden = function( elem ) { var width = elem.offsetWidth, height = elem.offsetHeight; return (width === 0 && height === 0) || (! jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css ( elem, "display" )) === "none"); }; jQuery.expr.filters.visible = function( elem ) { return !jQuery.expr.filters.hidden( elem ); }; }
Tip 3: Caching = Win. Each $(‘.whatever’) will re-run your search of the DOM and return a new collection Bad! - use caching! (ie. parents. find(‘.child’)) You can then do whatever.show()/hide/stuff to your heart’s content. var parents = $(‘.parents’); var children = $(‘.parents’).find(‘.child’) //bad
Tip 4: Chaining Almost all jQuery methods return a jQuery Object and support chaining After you’ve run a method on your selection, you can continue running more! Less code, easier to write and it runs faster! var parents = $(‘.parents’).doSomething().doSomethingElse();
Tip 5: Event Delegation Understand .bind(), .live() and .delegate() - do you REALLY know the differences? Delegates let you attach an event handler to a common parent of your elements rather than a discrete one to each of them Also fires for NEW DOM nodes too Use when binding same handler to multiple elements
Tip 6: The DOM isn’t a Database! jQuery lets you treat it like one, but that doesn’t make it so Every DOM insertion is costly Minimize by building HTML strings and using single a single append() as late as possible Use detach() if doing heavy interaction with a node then re-insert it when done
Tip 7: Avoid Loops. Nested DOM Selectors can perform better If not necessary, avoid loops. They’re slow in every programming language If possible, use the selector engine instead to address the elements that are needed There *are* places where loops can’t be substituted but try your best to optimize
Tip 8: Keep your code DRY /*Non-Dry*/ /*Let's store some default values in an array*/ var defaultSettings = {}; defaultSettings['carModel'] = 'Mercedes'; defaultSettings['carYear’] = 2010; defaultSettings['carMiles'] = 5000; defaultSettings['carTint'] = 'Metallic Blue';
/*Let's do something with this data if a checkbox is clicked*/ $('.someCheckbox').click(function(){
if (this.checked){ $('#input_carModel').val(activeSettings.carModel); $('#input_carYear').val(activeSettings.carYear); $('#input_carMiles').val(activeSettings.carMiles); $('#input_carTint').val(activeSettings.carTint);
DRY-er code /*Dry*/ $('.someCheckbox').click(function(){ var checked = this.checked; /* What are we repeating? 1. input_ precedes each field name 2. accessing the same array for settings 3. repeating value resets
What can we do? 1. programmatically generate the field names 2. access array by key 3. merge this call using terse coding (ie. if checked, set a value, otherwise don't) */ $.each(['carModel', 'carYear', 'carMiles', 'carTint'], function(i,key){ $('#input_' + v).val(checked ? defaultSettings[key] : ''); }); });
When in doubt - Perf test! jsPerf.com - easy way to create tests comparing the perf of different JS snippets Uses Benchmark.js - a neat benchmarking utility that works cross-platform Easy to share your code or modify other tests
Thats it! Thanks to Matt Baker over at WealthFront for his very useful reference material Twitter: @addyosmani / @addy_osmani For my blog: http://addyosmani.com GitHub: http://github.com/addyosmani