„Apps should be snappy, not sloppy”, that’s what Addy Osmani writes.
Also how true is this: “Best practices offer optimal approaches to solving problems. If we don’t follow them, browsers can end up having to do more work, which means more memory use and slower apps.”
A part of the steps we should take in order to get our apps snappier, is to improve our knowledge about the jQuery best practices and apply them.
These slides will help a lot: http://addyosmani.com/jqprovenperformance/
Here’s a summary, in case you’re too lazy to go through all 84 slides which I recommend nevertheless:
- Do performance testing with jsPerf.com (slides 8 – 11)
- Stay up to date (slides 13 – 18): always use the latest version of jQuery to have the latest performance improvements, bug patchesand regression fixes
- Know your jQuery selectors (slides 20 – 29): a selection can be made in many ways but not all selectors are as performant.
– Fastest: ID & Element Selectors => $(‘#Element, form, input’)
– Slowest: Class Selectors => $(‘.element’)
– Slowest: Pseudo & Attribute Selectors => $(‘:visible, :hidden’) or $(‘[attribute=value]’)
- Understand parents and children (slides 31 – 40): the topic is quite too large to summarize so just look at the slides.
- Use jQuery only if it’s absolutely necessary (slides 42 – 45): jQuery is JavaScript and sometimes JavaScript is more performant than jQuery.
– Over-use of attr(): ID selector: Instead of $(this).attr(“id”), which first parses the selector and creates a jQuery object, use simply this.id. The jQuery approach is 80-95% slower than directly accessing the attribute through the DOM element!
- Caching (slides 47 – 50): each $(‘.elem’) will re-run your search of the DOM and return a new collection. Caching decreases repeat selections so simply store the results of a selection for later re-use.
- Chaining (slides 52 – 54): most of the jQuery methods return an object and support chaining so after executing a method on a selection, you can continue executing more. Less code and easy to write!
var parents = $(‘.parents’).doSomething().doSomethingElse();
- Event delegation (slides 56 – 60): allow events to bubble up the DOM tree to a parent element so you bind to a single event handler rather than 100s and it works with elements in the DOM at runtime and those injected later.
– .bind(): attach event handler for elements, takes tim to bind for larger sets, doesn’t work with dynamically inserted elements.
– .live(): simplest, attach event handler for current and future matches for a selector, can’t chain to it (see point 7.)
– .delegate(): use when binding the same event handler to multiple elements, you can specify the particular DOM element
- The DOM isn’t a database (slides 62 – 68):
– Each DOM insertion is costly: use .append(), .insertBefore(), .insertAfter() only if absolutely necessary.
– Multiple appends are 90% slower than building HTML strings in-memory and using a single .append() instead.
– Traversing the DOM to retrieve .text() and .html() is not the most optimal approach.
– Use.detach() when doing heavy interaction with a node and re-insert the node to the DOM once you’re done, 60% faster than working with undetached nodes.
– Use $.data(‘#elem’, key, value) instead of $(‘#elem’).data(key, value), which creates an overhead by creating a jQuery object and doing data parsing.
- Understand loops (slides 70 – 73):
– jQuery iterations over collections are easy but not always the most performant. Actually native for and while loops are faster than $.each().
– Avoid loops unless absolutely necessary! Use the selector engine instead to access the needed elements.
- Avoid constructing new jQuery objects unless necessary (slides 75 – 78):
– Bad: $(‘a’).map(function() { return $(this).text(); } );
- Keep the code dry (=minimal) (slides 79 – 82): repeating the same code increases the size of our code and reduces productivity.