Your SlideShare is downloading. ×
0
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

jQuery Anti-Patterns for Performance

1,505

Published on

jQuery Anti-Patterns for Performance

jQuery Anti-Patterns for Performance

Published in: Education
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,505
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
42
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • update the taskspeed shit.\ndelegation facts.\n
  • i hang in #jquery so a lot of examples are from real code discussed there.\n
  • \n
  • \n
  • \n
  • \n
  • like copypasting a line or three of code\n
  • \n
  • \n
  • \n
  • rebecca murphey will be discussing this technique a lot more\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • the convenience of context will incur the cost of three extra if() statements in jQuery.fn.init()\n
  • \n
  • selectors. ugh.\n
  • did it because i wanted to study.\nthe old ones are probablyw ayyyyy easier to study as the new ones use some crazy techniques\n
  • did it because i wanted to study.\nthe old ones are probablyw ayyyyy easier to study as the new ones use some crazy techniques\n
  • \n
  • before sizzle it was LTR. sizzle changed it.\n
  • before sizzle it was LTR. sizzle changed it.\n
  • before sizzle it was LTR. sizzle changed it.\n
  • be brief on the left\nthe more you can filter down the righthandmost expression, the faster it will run.\n
  • id is grabbed. optimization\n
  • in my testing it didnt speed up basic selecting.\n
  • \n
  • css engine too.\n
  • \n
  • TDs and LI’s etccc\n
  • \n
  • \n
  • \n
  • \n
  • document.body as an append target is WIN\n
  • \n
  • \n
  • padolsey’s research on animate()\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • strings take up a lot of space, so allowing them to be munged helps a lot\ncompress it and look for repetition\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • DRY obviously\n
  • DRY obviously\n
  • \n
  • really understand truthy and falsy ness\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript

    • 1. jQuery Anti-Patterns forPerformance &CompressionPaul IrishNC JavaScript Camp ’10
    • 2. jQuery Anti-Patterns forPerformance &CompressionPaul IrishNC JavaScript Camp ’10
    • 3. Me.Interaction Designer at Molecular, Inc.jQuery Team Member - Dev. Relations @paul_irishhttp://paulirish.com Front-end development bloghttp://aurgasm.us Eclectic music blog
    • 4. Performance
    • 5. Performance
    • 6. wassup shawty? how u doin’ Taskspeed Test Lines of Code20015010050 0 YUI Dojo 1.3.1 Dojo 1.2.3 Qooxdoo MooTools Prototype.js jQuery PureDOM
    • 7. Oft cited best practices Cache length during loops Cache your selections Leverage documentFragment Append new content outside the loop
    • 8. Oft cited best practices Cache length during loops// appending inside. bad.$.each(reallyLongArray, function(count, item) { Cache your selections var newLI = <li> + item + </li>; Leverage documentFragment $(#ballers).append(newLI);}); Append new content outside the loop// documentFragment off-DOMvar frag = document.createDocumentFragment();$.each(reallyLongArray, function(count, item) { var newLI = <li> + item + </li>; frag.appendChild(newLI[0]);});$(#ballers)[0].appendChild(frag);
    • 9. var newLI = <li> + item + </li>; $(#ballers).append(newLI);});Oft cited best practices// documentFragment off-DOMvar frag = document.createDocumentFragment(); Cache length during loops$.each(reallyLongArray, function(count, item) { var newLI = <li> + item + </li>; Cache your selections frag.appendChild(newLI[0]);}); Leverage documentFragment$(#ballers)[0].appendChild(frag); Append new content outside the loop// string concatenate and set innerHTMLvar myhtml = ;$.each(reallyLongArray, function(count, item) { myhtml += <li> + item + </li>;});$(#ballers).html(myhtml);
    • 10. Keep things DRY If you’re repeating yourself, you’re doing it wrong
    • 11. Moar DRY plz?if ($ventfade.data(currently) != showing) { $ventfade.stop();}if ($venthover.data(currently) != showing) { $venthover.stop();}if ($spans.data(currently) != showing) { $spans.stop();} from http://mt-ventures.com/_js/global.js
    • 12. All clean! Thxvar elems = [$ventfade,$venthover,$spans];$.each(elems,function(k,v){ if (v.data(currently) != showing){ v.stop(); }})
    • 13. Architecture Anti-Patterns Anonymous functions bound everywhere suck$(document).ready(function(){ ... $(#magic).click(function(e){ $(#yayeffects).slideUp(function(){ ... }); }); $(#happiness).load(url+ #unicorns,function(){ ... })});
    • 14. Architecture - Object Literalvar PI = { onReady : function(){ ... $(#magic).click(PI.candyMtn); $(#happiness).load(url+ #unicorns,PI.unicornCb); }, candyMtn : function(e){ $(#yayeffects).slideUp(PI.slideCb); }, slideCb : function(){ ... }, unicornCb : function(){ ... }}$(document).ready(PI.onReady);
    • 15. Architecture - Object Literal Advantages: Easier to navigate and discuss Profilers give you actual names to work with You can execute these from firebug console You can write unit tests against them
    • 16. Anti-Pattern: The requery// create and append your element$(document.body).append("<div class=baaron/>");// requery to bind stuff$("div.baaron").click(function(){});// better:// swap to appendTo to hold your elem$("<div class=baaron/>") .appendTo(document.body) .click(function(){});
    • 17. $(‘#whats .the’,context)
    • 18. This is not the .context property // find all stylesheets in the body var bodySheets = $(style,document.body); bodySheets.context // ==> BODY element Ignore that for the moment, I know no one that’s found a use
    • 19. $(‘#whats .the’,context) Never pass it a selector string. Ever. No performance gain vs $(root).find(selector) var arms = $(div.robotarm, #container); // instead do: var arms = $(#container).find(div.robotarm);
    • 20. $(‘#whats .the’,context) You typically pass it this, but it’s purely a convenience to avoid find() $(form.comments,this).submit(captureSubmit); // exact same as $(this).find(form.comments).submit(captureSubmit); Which is more readable?$(.reply_form, $(this).closest(.comment)).hide();$(this).closest(.comment).find(.reply_form).hide();
    • 21. The Crowd Say Bo Selector
    • 22. Come on, my selectorSelector engines have come a long, long way.
    • 23. Come on, my selectorSelector engines have come a long, long way.
    • 24. Come on, my selectorEngines work in different waysTop-down, bottom-up, function creation, other crazy shit// from NWMatcher:// selecting .outmost #outer spanT=e.nodeName;if(T=="SPAN"||T=="span"){while((e=e.parentNode)&&e.nodeType==1){if((n=e.getAttributeNode("id"))&&n.value=="outer"){if((e=e.parentNode)&&e.nodeType==1){C=e.className;if(C&&(" "+C+" ").indexOf(" outmost ")>-1){r[X++]=N;continue main;}}}}}
    • 25. Selector engines, parse direction Left to right (Top-down) Right to left (Bottom-up) Mootools Sizzle Sly YUI 3 Peppy NWMatcher Dojo Acme Ext JS Prototype.js details: http://alexsexton.com/selectors/
    • 26. Selector engines, parse direction div.data table.attendees .gonzalez Left to right (Top-down) Right to left (Bottom-up) Mootools Sizzle Sly YUI 3 Peppy NWMatcher Dojo Acme Ext JS Prototype.js details: http://alexsexton.com/selectors/
    • 27. Selector engines, parse direction Left to right (Top-down) Right to left (Bottom-up) Mootools Sizzle Sly YUI 3 Peppy NWMatcher Dojo Acme Ext JS Prototype.js details: http://alexsexton.com/selectors/
    • 28. Selector engines, parse direction Left to right (Top-down) Right to left (Bottom-up) Mootools Sizzle Sly YUI 3 Peppy NWMatcher Dojo Acme querySelectorAll (qSA) Ext JS Prototype.js details: http://alexsexton.com/selectors/
    • 29. Selector Optimization Specific on the right, light on the left // lets find scott div.data .gonzalez // specific on right, light on the left .data td.gonzalez tag.class if possible on your right-most selector. just tag or just .class on left.
    • 30. Selector Optimization Of course, descending from an #id is best// basic #id-based selectorvar arms = $(#container div.robotarm);// hyper-optimized #id case first, then find:var arms = $(#container).find(div.robotarm);
    • 31. Selector Optimization Don’t be needlessly specific // lets find scott .data table.attendees td.gonzalez // better: drop the middle .data td.gonzalezA flatter DOM helps, so move to HTML5 Also a wider range of tags speeds up filters
    • 32. Selector Optimization Avoid the universal selector Avoid the implied universal selector $(.buttons > *) // terribly costly $(.buttons).children() // much better $(.gender :radio) // implied universal $(.gender *:radio) // exact same, explicit now $(.gender input:radio) // much better
    • 33. Selector Optimization Google PageSpeed’s efficient selectors analysis MDC: Writing Efficient CSS https://developer.mozilla.org/en/Writing_Efficient_CSS Benchmark.js http://code.paulirish.com/sandbox/benchmark.js
    • 34. Event Delegation function delegate(type, delegate, handler) { return $(document).bind(type, function(event) { var target = $(event.target); if (target.is(delegate)) { return handler.apply(target, arguments); } }); } delegate(click,td.jehl,createRockstar); // and with live(): $(td.jehl).live(click,createRockstar);
    • 35. Event Delegationlive() isn’t just for dynamic contentSpeeds up page load Only one event handler is bound vs manyGood for >3 elements all getting the same handler // using live(), skipping selection on load var jqElem = $(document); jqElem.selector = li.ui; jqElem.live(dblclick, dblhandler);
    • 36. Event Delegationlive() isn’t just for dynamic contentSpeeds up page load Only one event handler is bound vs manyGood for >3 elements all getting the same handler // using live(), skipping selection on load var jqElem = $(document); jqElem.selector = li.ui; jqElem.live(dblclick, dblhandler);
    • 37. Event Delegation delegate() bakes in huge performance gains explicit context reduces overhead by ~80% Use it instead of live() if possible// awkward but equivalent$(a.trigger,$(#container)[0]).live(click,handlerFn)// so damn fine$(#container).delegate(click,a.trigger,handlerFn)
    • 38. Event Delegation new 1.4 in .2! delegate() bakes in huge performance gains explicit context reduces overhead by ~80% Use it instead of live() if possible// awkward but equivalent$(a.trigger,$(#container)[0]).live(click,handlerFn)// so damn fine$(#container).delegate(click,a.trigger,handlerFn)
    • 39. The DOM is slowPull elements off the DOM while you toy with themvar table = $(#some-table);var parent = table.parent();table.detach();table.addLotsAndLotsOfRows();parent.append(table);
    • 40. The DOM is slowPull elements off the DOM while you toy with themvar table = $(#some-table);var parent = table.parent(); newtable.detach(); in 1 .4table.addLotsAndLotsOfRows();parent.append(table);
    • 41. Minimize DOM touches Use classes, but if a style change user-selected: jQuery(a.swedberg).css(color, #BADA55); jQuery(<style type="text/css"> a.swedberg { color: BADA55; } </style>) .appendTo(head);3000 Timings for X elements2250 (1000 iterations)1500 css() style tag750 0 1 5 10 20 50
    • 42. Minimize DOM touches
    • 43. Don’t treat jQuery as a Black Box Use the source as your documentation Add this to your bookmark bar, NOW! http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js http://bit.ly/jqsource Determine which are convenience methods: getScript: function( url, callback ) { return jQuery.get(url, null, callback, "script"); }, getJSON: function( url, data, callback ) { return jQuery.get(url, data, callback, "json"); },
    • 44. Don’t treat jQuery as a Black Box Learn the lesser-known methods map(), slice(), stop(), (de)queue(), prevAll(), pushStack(), inArray() , etc // index() in jQuery <= 1.3.2 $(#rdworth).parent().children().index( $(#rdworth)[0] ) // using prevAll() is 10% faster (also sexier) $(#rdworth).prevAll().length // in jQuery 1.4 $(#rdworth).index()
    • 45. Don’t act on absent elements jQuery is very kind and doesn’t throw errors at you Don’t assume it’s just fine to do $(#doesntexist).slideUp() // this will execute genFx(), speed() and animate() // before it hits an each() jQuery UI widgets have a lot of overhead you’ll hit
    • 46. Don’t act on absent elements jQuery.fn.doOnce = function(func){ this.length && func.apply(this); return this; } $(li.cartitems).doOnce(function(){ // make it ajax! o/ });
    • 47. Don’t act on absent elements $.fn.plugin = function(opts){ if(!this.length) return this; var opts = $.extend(...... ... return this.each(...
    • 48. Setter Methodsview-source:setters.js
    • 49. newNew Element Creation 1.4 ! injQuery("<div/>", { id: "foo", rel : "something" css: { height: "50px", width: "50px", color: "blue", backgroundColor: "#ccc" }, click: function() { $(this).css("backgroundColor", "red"); }}).appendTo("body");
    • 50. neweq(), first(), last() 1.4 ! invar lastelem = $elems.eq(-1); // get() too!$(#nav li:first) === $(#nav li).first()$(#nav li:last) === $(#nav li).last()
    • 51. Data()// regular:$(elem).data(key,value);// omg like 10x faster:$.data(elem,key,value);
    • 52. Compression
    • 53. CompressionYUI Compressor Sits on Rhino.Comments, whitespace, variable replacement//it already does these micro-optimizations:object[prop] ==> object.prop{key:123} ==> {key:123}jons apostophes ==> "jons apostrophes"bigass + string ==> bigass string
    • 54. Variable definition// old n busted // new hotnessvar test1 = 1; var test1 = 1,var test2 = function() { test2 = function() { // function code // function code}; },var test3 = test2(test1); test3 = test2(test1);
    • 55. Munge the primitivesDefine shortcuts at the top of your scope Good for both compression and scope chain traversalvar TRUE = true, FALSE = false, NULL = null, window = self, undefined = undefined;
    • 56. Munge the primitivesDefine shortcuts at the top of your scope Good for both compression and scope chain traversalvar TRUE = true, FALSE = false, NULL = null, window = self, undefined; undefined = undefined;
    • 57. Munge the primitives(function(){ var window = this, document = document,undefined; /* code */})();(function(window, document, undefined){ /* code */})(this,this.document);
    • 58. var str=‘Let’s put this intoaction’ // html.no-js html> <!doctype ==> html.js var elem = document.getElementsByTagName(html)[0]; elem.className = elem.className.replace(no-js,js); <html class="no-js"> // quicker reference, safer replace <head> var elem = document.documentElement; elem.className = elem.className.replace(/bno-jsb/,js); <script> // one// change the html class to js line ftw! // in the head, no FOUC document.documentElement.className = document.documentElement.className.replace(/bno-jsb/, </script> js); </body> // shorter with a self-executing anonymous function (function(B){B.className=B.className.replace(/bno-jsb/,
    • 59. var str=‘Let’s put this intoaction’ // html.no-js ==> html.js var elem = document.getElementsByTagName(html)[0]; elem.className = elem.className.replace(no-js,js); // quicker reference, safer replace var elem = document.documentElement; elem.className = elem.className.replace(/bno-jsb/,js); // one line ftw! document.documentElement.className = document.documentElement.className.replace(/bno-jsb/, js); // shorter with a self-executing anonymous function (function(B){B.className=B.className.replace(/bno-jsb/,
    • 60. // html.no-js ==> html.jsvar str=‘Let’s put this intovar elem = document.getElementsByTagName(html)[0];elem.className = elem.className.replace(no-js,js);action’// quicker reference, safer replacevar elem = document.documentElement;elem.className = elem.className.replace(/bno-jsb/,js);// one line ftw!document.documentElement.className =document.documentElement.className.replace(/bno-jsb/,js);// shorter with a self-executing anonymous function(function(B){B.className=B.className.replace(/bno-jsb/,js)})(document.documentElement);// pass className, object string notation(function(H,C){H[C]=H[C].replace(/bno-jsb/,js)})(document.documentElement,className)
    • 61. Conditionals// old n bustedif ( type === foo || type === bar ) {}// regex testif ( /^(foo|bar)$/.test(type) ) {}// obj literal lookup (smaller if <5 items)if ( ({foo:1,bar:1})[type] ) {}
    • 62. Logic and Ternary operands// basic function detectiondocument.querySelectorAll && document.querySelectorAll(a:nth-child(2))// assignment is legal, but it evaluates to the right expressioncallback && (isCallbackCalled = true) && callback(returnVal);// call or cache the callback function(isCallbackCalled || returnVal) ? fn(returnVal) : (callback = fn);// inline function callsisToday(Saturday) && Math.round(Math.random()) && $(#winnar).show()// if JSON2.js or Native JSON is present, otherwise eval.data = window.JSON && JSON.parse(data) || eval((+data +));
    • 63. Write maintainable code As a developer, you should work first and foremost for the user of your products. The second most important person to work for is the developer that takes over from you. - Christian Heilmann
    • 64. Comments/*! * Will not be removed by YUI Compressor */// for quick toggling on and off:/* */ aaaahYeah();/* *//* * / ohHellNo();/* */
    • 65. Compression ToolsCompressorRater http://compressorrater.thruhere.net/YUI Compressor front-end http://refresh-sf.com/yui/
    • 66. Thanks, ya’ll. Slides at http://paulirish.com/perf @paul_irishthx: Alex Sexton, Ben Alman, Adam Sontag, James Padolsey, temp01, #jquery on Freenode
    • 67. todoshadow effect to code samplesmore context research and this: http://groups.google.com/group/jquery-dev/msg/b4b7935a4013dfe7 and http://ispeakwebstuff.co.uk/web-design-development-tutorials/clever-jquery-selectors/
    • 68. ` // pngfix for IE6 // e.g. FL.pngfix(img.bigProdShot,a.thumb); pngfix : function(sel){ // conditional comments for inclusion of that js. if (typeof DD_belatedPNG == undefined){ return; } else { // delay pngfix until window onload $(window).load(function(){ $(sel).each(function() { DD_belatedPNG.fixPng(arguments[1]); }); }); } } // end of FL.pngfix()

    ×