tips for better javascript

Upload: john-dunn

Post on 05-Jan-2016

235 views

Category:

Documents


0 download

DESCRIPTION

Would you like to write better Javascript? This presentation will help you do that.

TRANSCRIPT

PowerPoint Presentation

5 TipsFor Better@toddanglinNEWtalk5 Tips for Better JavaScriptLove it or hate it, JavaScript is playing an increasingly important role in the next generation of web and mobile apps. As code continues to move from the server to the client, JavaScript is being used to domore than simple HTML manipulation. Be prepared for this transition and make sure the JavaScript you write is optimized and ready to perform on desktops and devices! In this session, you will learn tenpractical tips that you can use today to write faster, more maintainable, memory friendly JavaScript. You will also learn techniques for testing, debugging, and profiling JavaScript apps.1

JAVASCRIPT!

JAVASCRIPT.@toddanglinBrought to you by @[email protected]

Kendo UI: Everything you need to build sites & mobile apps with HTML and JavaScript (http://www.kendoui.com)

4

Why JavaScript?

WHY?!AGENDA:- Why JavaScript? Why?!- Most Common JS Problems- TIPS- Future of JavaScript

5Its the first?JavaScript uses syntax influenced by that of C. JavaScript copies many names and naming conventions from Java, but the two languages are otherwise unrelated and have very different semantics. The key design principles within JavaScript are taken from the Self and Scheme programming languages.http://en.wikipedia.org/wiki/JavaScript

6Its the best?Its the easiest?Its the fastest?Its everywhere.NOTES:HistoryEvolutionThe IE Connection (IE6 memory)Modern JS EnginesBOTTOM LINE: Only Cross Platform Language Solution

10

JavaScript.I am your father.No, really.Brendan Eich.Netscape.Netscape also wanted a lightweight interpreted language that would complement Java by appealing to nonprofessional programmers, like Microsoft's VB11JS had to 'look like Java' only less so, be Javas dumb kid brother or boy-hostage sidekick. Plus, I had to be done in ten days or something worse than JS would have happenedCredit: Brendan Eich via WikipediaSource: http://www.jwz.org/blog/2010/10/every-day-i-learn-something-new-and-stupid/#comment-1021

Brendan further said that JavaScript saved the world from VBScripthttp://www.jwz.org/blog/2010/10/every-day-i-learn-something-new-and-stupid/#comment-104912

:

:::

Java is to JavaScriptASCar is to Carpet

Netscape was going to release JavaScript as LiveScript. Last minute change produced JavaScript.13Sept 1995NetscapeAug 1996MicrosoftJune 1997ECMAScript//Mar 1999XHRFeb 2005AjaxAug 2001IE6FirefoxSafariChromeMobileHOW DID JAVASCRIPT BECOME UBIQUITOUS?

Netscape shipped first in Netscape 2Microsoft support added in IE3 (JScript)

Other environments adopted JavaScript-like script languages: ActionScript (Flash), PDFs, Qt

14JavaScript won by default.

If you're the last man left on earth, it doesn't matter how ugly you are when the women come to re-populate the planet.Scott Koonhttp://www.codinghorror.com/blog/2007/05/javascript-the-lingua-franca-of-the-web.html15

Cant Beat em,Join em.Modern JavaScriptFaster. Easier. Better.Contributing factors:New JS engines (V8)CPU speed (more local processing power)Better debugging toolsBetter understanding of language (closures, patterns, functional programming, JSLint)17

Chrome is 10x faster than IE7 (IE6 too old to test)

Used crude relative test: http://jsbenchmark.celtickane.com18

http://geekmontage.com/firefox-vs-chrome-vs-ie/19Attwoods Law:Any application that can be written in JavaScript, will eventually be written in JavaScript2007http://www.codinghorror.com/blog/2007/07/the-principle-of-least-power.html

The Principle of Least Power

20MOST COMMON PROBLEMSSlow ExecutionMemory leaksPoor Code OrganizationLack of Understanding

5(ish) TIPSFrom real masters:JordanIvanTsvetomirAtanasBurkeJohnBrandon

Jordan Ilchev, Icenium Team LeadIvan Ivanov, Sr DeveloperBurke Holland, Evangelist, Kendo UIJohn Bristowe, Evangelist, Kendo UITsvetomir Tsonev, Sr Developer, Kendo UI24TIP #1jQuery is a friendthat will stab you in the back.Prove ItjQuery built for convenience, not for performance.PERF PROOF: http://jsperf.com/id-vs-class-vs-tag-selectors/46

Note: This in general is applicable to native JavaScript methods too, like document.getElementById() not limited to jQuery only objects DOM lookups are slow especially if DOM is huge.Instead of this:$('#test').bind('click', function() { /**/ });$('#test').css('border', '1px solid #999');Better use jQuery Method chaining:$('#test').bind('click', function() {/**/ }) .css('border', '1px solid #999');Or cache jQuery object:var $test = $('#test');$test.bind('click', function() {/**/ });$test.css('border', '1px solid #999');(Performance comparison here: http://jsperf.com/jquery-chaining/12) (~+30% here, but it stacks on each additional method call)25SUB-TIP1.1CACHE OBJECTS$("#myDiv").css("color","red");$("#myDiv").css("opacity",1);BAD$("#myDiv").css("color","red").css("opacity",1);BETTERvar $myDiv = $("#myDiv");$myDiv.css("color","red");$myDiv.css("opacity",1);BEST*Prove ItPRO TIP CONVENTION: Name jQuery variables with $ (ie $myObject)

PERF TEST: http://jsperf.com/caching-jquery-objects-perf

http://jsbin.com/udizam/226SUB-TIP1.2NATIVE LOOPS$.each(arr, function (i) {i / 2;});BADarr.forEach(function (i) {i / 2;});BETTERvar i = 0, len = arr.length;for (i = 0; i < len; i += 1) {i / 2;}BEST*Prove ItPERF TEST: http://jsperf.com/for-vs-foreach-vs-each/3

- Caching the array length improves perf by about 15% (http://jsperf.com/for-vs-foreach-vs-each/24)- Technically a reverse (count down) for loop is faster (15%) than count-up loop, but much harder to read/use

27TIP #2Avoid Global VariablesThey're slow & rude.Global variables pollute the JS app and are slower to use in code. Harder to be a good JS "neighbor" with global variables (collide with other JS code).

Better to use local variables, cached variable, or closures28

function add(num1, num2){ return num1 + num2;}

var result = add(5, 10);12:43Prove ItChart credit: http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html

PERF TEST: http://jsperf.com/global/2Microsoft ASP.NET Connections29Updates will be available at http://www.devconnections.com/updates/LasVegas_Fall11/ASPvar name = "Todd";function sayHello(){alert(name);}function sayHello(){ var name = "Todd";alert(name);}12:43BADBETTERClosures & Module Patternvar app = (function(){ var _name = "Todd"; return{ sayHello: function(){ alert(_name); } }}());

app.sayHello();12:44BEST(ISH)Pattern sometimes referred to as: MODULE EXPORThttp://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

BE CAREFUL WITH CLOSURES: Most common source of memory leaks in modern appshttps://developers.google.com/speed/articles/optimizing-javascript

Circular Reference Memory Leaks: http://blogs.msdn.com/b/ericlippert/archive/2003/09/17/53028.aspx

32SUB-TIP2.1SUPER PATTERN(function(window,$,c){ var _private = "Todd"; function privateClass(){} function myWidget(){} myWidget.prototype.doSomething = function(){}

window.myWidget = myWidget;}(window,jQuery,console);Self-Executing Anonymous Functions + Global Imports + PrototypeProve ItPERF TEST: http://jsperf.com/prototype-vs-closures/20

Suppose you develop a widget. The widget has a number of axillary classes. If you just define them globally they will pollute the global window class, meaning they will be available from everywhere. Instead consider the following definition: (function (window) { function classA () {} function classB () {} function myWidget () {} myWidget.prototype.method1 = function () { } window.myWidget = myWidget; }) (window, undefined);This is the pattern which jQuery follows. Now the only available global definition will be of myWidget. classA and classB remain hidden in the anonymous function. If you look closely in the definition, you will see the that window and undefined are passed to the anonymous function. Passing anonymous guaranties that undefined will be available in the scope of this function and will prevent you from someone who accidentally did something like:undefined = true;before your function. Also, if you use some minifier, it will replace all occurrences of window with some shorter name. Of course you can pass as much params as you wish, thus assuring that these objects exist in the scope of your anonymous function.33TIP #3Bind to Events & Pub/SubJust listen.- Binding to delegates is less brittle, easier to avoid memory leaks- Pub/Sub is super flexible, less coupling34

Click Me

$(function(){$(#btn").on("click",sayHello);});12:44BADBETTERThe scope of an inline event bind is GLOBAL!

Inline event handlers can also cause memory leaks in IE: https://developers.google.com/speed/articles/optimizing-javascript35$(document).on("click","button", sayHello);12:44BESTWhy?Old jQuery syntax: .delegate36SUB-TIP3.1UNBINDING EVENTS$(document).off("click","button");$(document).remove("button");OREvery time you need to dispose a DOM element, make sure you unbind all of its events, unless you want to come up with a memory leak.

Whenever you bind an event handler to an event, you tell the processor to allocate memory for it. The more event handlers you have running at the same time, the more memory you are using. This is why it's important to unbind or detach your event handlers soon as you no longer need them.http://www.learnjquery.org/newsletter/Tutorial-3-jquery-events.html

37function doSomthing{...doSomethingElse();

doOneMoreThing();}12:44BADEvent listening PUB/SUB38function doSomething{...$.trigger("DO_SOMETHING_DONE");}

$(document).on("DO_SOMETHING_DONE", function(){ doSomethingElse();});12:44BETTERfunction doSomething(){var dfd = new $.Deferred();//Do something async, then...//dfd.resolve();

return dfd.promise();}

function doSomethingElse(){$.when(doSomething()).then(//The next thing);}12:44ALSO BETTERTIP #4Don't fondle the DOM.Go with the flow.Reducing the time spent changing the DOM improves perf. Using templates improves readability/maintainability.

Instead of this:var $list = $('#mylist').append('

  • ');for (var i = 0, l = itemlist.length; i < l; i++) { $list.append('
  • ' + itemlist[i] + '');}better this:var $list = $('
    • ');for (var i = 0, l = itemlist.length; i < l; i++) { $list.append('
    • ' + itemlist[i] + '');}$('#mylist').append($list);(Performance comparison here: http://jsperf.com/jquery-dom-manipulation/3) (up to x5 in this case)

      41My Awesome PageCopyright Fo'evaLorem ipsumy samplish jibber jabbish text only meant to serve as a placeholder, and much like Pi, should never repeat or be read much beyond the first few characters.function doSomething{...var $list = $("body").append("

      • ");for(var i = 0; i < 10; i++){$list.append("
      • "+ i +"") }}

        12:44BADfunction doSomething{...var $domChunk = $("

        • ");for(var i = 0; i < 10; i += 1){$domChunk.append("
        • "+ i +""); }$("body").append($domChunk);}

          12:44BETTERSUB-TIP4.1DOM SPEED WITHSTRINGS & INNERHTMLfunction doSomething{...var domString = "

          • ";for(var i = 0; i < 10; i += 1){domString += "
          • "+ i +""; }domString += "

          "$("body")[0].innerHTML = domString;}

          Prove ItPERF TEST: http://jsperf.com/jquery-dom-manipulation/4

          When you want to dynamically build html, prefer string concatenation like:var html = some paragraph;html += another paragraph;$(#placeHolder).html(html);over DOM object creation and appending/prepending like: var p1 = document.createElement('p'); p1.innerHTML = "some paragraph"; document.body.appendChild(p1); var p2 = document.createElement('p); p2.innerHTML = "another paragraph"; document.body.appendChild(p2);assigning directly to the innerHTML proves to be the fastest method for html creation.45

          • #for(var i = 0; i < data.length; i += 1){#
          • #= data[i] # #}#

          function doSomething(){var myData = [1,..,10];var template = kendo.template($("#tmp").html());$("body").append(template(myData));}12:44BESTProve ItPERF TEST: http://jsperf.com/jquery-dom-manipulation/546TIP #5Learn a module pattern.And use it.Common Examples: RequireJS, CommonJS

          Applications of any size are painful to manage without a module pattern.

          47PERFORMANCECONVENIENCEWe want to reduce JavaScript files for performance (fewer network requests), BUT

          One large JS file is hard to maintain. We'd really prefer more modular files.48A.jsB.jsManual (index.html)

          Module Loader (main.js)require(["A","B"], function(){//Dependencies are loaded});USE JSLINTGuaranteed to Hurt Your Feelings12:44BONUSTIPSMINIFY YOUR JSWords are for humans.MASTER BROWSER DEV TOOLSDebug JavaScript where it runs.JSLint by Douglas Crockford

          Code quality tool for JavaScript

          http://www.jslint.com/

          Microsoft ASP.NET Connections50Updates will be available at http://www.devconnections.com/updates/LasVegas_Fall11/ASPDebuggingconsole.log()Fix IE

          if (!this.console) { window.console = { log: function() {} };}

          12:44More complete fix by Paul Irish: http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/Microsoft ASP.NET Connections53Updates will be available at http://www.devconnections.com/updates/LasVegas_Fall11/ASPResources for StudyBooksJavaScript: The Good Parts (Crockford)JavaScript: The Definitive Guide (Flanagan)JavaScript Patterns (Stefanov)High Performance JavaScript (Zakas)12:44Microsoft ASP.NET Connections54Updates will be available at http://www.devconnections.com/updates/LasVegas_Fall11/ASPconsole.clear();

          JAVASCRIPT, mon.A&[email protected] | @toddanglinwww.KendoUI.com