SlideShare a Scribd company logo
flickr.com/photos/jontysewell/4526861658/




             Maintainable JavaScript
                                   Nicholas C. Zakas | @slicknet
Who's this guy?




     5 years             Co-Creator                Contributor,
Tech Lead, Yahoo!        csslint.net            Creator of YUI Test




 Author         Lead Author       Contributor           Lead Author
Maintainability
Why do we care?
flickr.com/photos/indraw/4857101224/




       Most of your time is spent maintaining code
Who cares?




Your Employer           Your Co-workers,
                       Present and Future
flickr.com/photos/protestphotos1/4726566233/




                          We all want to be rock stars
                 "Don't mess with my process, man! It's about the music!"
flickr.com/photos/the_junes/3120810156/




                        At work, you're part of a team
                  Awesome happens when everyone is on the same page
Maintainable code is



Understandable        Adaptable   Debuggable


                                         Testable
          Intuitive       Extendable
Code Conventions


               Understandable



                         Intuitive
flickr.com/photos/29271559@N02/5799773313/




      "Programs are meant to be read by humans and
        only incidentally for computers to execute."
                                             Donald Knuth
flickr.com/photos/polinasergeeva/3052378826/




                                                              Tabs for
                                                             indentation




                4 spaces for
                 indentation




                                               Indentation
if (wl && wl.length) {
            for (i = 0, l = wl.length; i < l; ++i) {
         p = wl[i];
         type = Y.Lang.type(r[p]);
         if (s.hasOwnProperty(p)) { if (merge && type
    == 'object') {

    Y.mix(r[p], s[p]);
} else if (ov || !(p in r)) {
                    r[p] = s[p];
                }
            }
        }
    }
if (wl && wl.length) {
    for (i = 0, l = wl.length; i < l; ++i) {
        p = wl[i];
        type = Y.Lang.type(r[p]);
        if (s.hasOwnProperty(p)) {
            if (merge && type == 'object') {
                Y.mix(r[p], s[p]);
            } else if (ov || !(p in r)) {
                r[p] = s[p];
            }
        }
    }
}
flickr.com/photos/polinasergeeva/3052378826/




                                               Comments
/**
 * Returns a new object containing all of the properties of
 * all the supplied objects. The properties from later objects
 * will overwrite those in earlier objects. Passing in a
 * single object will create a shallow copy of it. For a deep
 * copy, use clone.
 * @method merge
 * @for YUI
 * @param arguments {Object*} the objects to merge.
 * @return {object} the new merged object.
 */
Y.merge = function() {
    var a = arguments, o = {}, i, l = a.length;
    for (i = 0; i < l; i = i + 1) {
        Y.mix(o, a[i], true);
    }
    return o;
};
                     Every method
if (mode) {
    switch (mode) {
        case 1: // proto to proto
            return Y.mix(r.prototype, s.prototype, ov, wl, 0,
                         merge);
        case 2: // object to object and proto to proto
            Y.mix(r.prototype, s.prototype, ov, wl, 0, merge);
            break; // pass through
        case 3: // proto to static
            return Y.mix(r, s.prototype, ov, wl, 0, merge);
        case 4: // static to proto
            return Y.mix(r.prototype, s, ov, wl, 0, merge);
        default: // object to object is what happens below
    }
}



             Difficult-to-understand code
while (element &&(element = element[axis])){ //NOTE: assignment
    if ( (all || element[TAG_NAME]) &&
       (!fn || fn(element)) ) {
            return element;
    }
}




        Code that might seem to be wrong
Naming
flickr.com/photos/kaatje/243834320/
Naming
• Use logical names for variables and functions
   – Don't worry about length
• Variable names should be nouns
• Function names should begin with a verb (i.e.
  getName())
   – Functions return booleans should begin with
     "is", such as isValid()
• Avoid useless names such as foo and temp
if (wl && wl.length) {
    for (i = 0, l = wl.length; i < l; ++i) {
        p = wl[i];
        type = Y.Lang.type(r[p]);
        if (s.hasOwnProperty(p)) {
            if (merge && type == 'object') {
                Y.mix(r[p], s[p]);
            } else if (ov || !(p in r)) {
                r[p] = s[p];
            }
        }
    }
}
Loose Coupling


            Adaptable   Debuggable



                 Extendable
Front End Layers



Presentation     Behavior
   (CSS)       (JavaScript)
                Base JS
      Data/Structure
         (HTML)
Don't cross the streams
<button onclick="doSomething()">Click Me</button>




     Keep JavaScript out of HTML
var element = document.getElementById("container");
element.innerHTML = "<div class="popup"></div>";




            Keep HTML out of JavaScript
.foo {
    width: expression(document.offsetWidth + "px");
}




             Keep JavaScript out of CSS
var element = document.getElementById("container");
element.style.color = "red";
element.style.cssText = "background:blue;border:1px solid red";




             Keep CSS out of JavaScript
Programming Practices


              Adaptable Debuggable


                               Testable
                 Extendable
//the wrong way!!!
function handleClick(event){

    var popup = document.getElementById("popup");
    popup.style.left = event.clientX + "px";
    popup.style.top = event.clientY + "px";
    popup.className = "reveal";

}




    Event handlers should only handle events
//better, but still wrong
function handleClick(event){
    showPopup(event);
}

function showPopup(event){
    var popup = document.getElementById("popup");
    popup.style.left = event.clientX + "px";
    popup.style.top = event.clientY + "px";
    popup.className = "reveal";
}




        Don't pass the event object around
//win!!
function handleClick(event){
    showPopup(event.clientX, event.clientY);
}

function showPopup(x, y){
    var popup = document.getElementById("popup");
    popup.style.left = x + "px";
    popup.style.top = y + "px";
    popup.className = "reveal";
}




        Properly separated event handling
//don't add new methods
Array.prototype.awYeah = function(){
    alert("Aw yeah!");
};

//don't override methods
YUI.use = function(){
    alert("Aw yeah!");
};




        Don't modify objects you don't own
        If you didn't define the object yourself, you don't own it
nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/
function handleClick(event){
    showPopup(event.clientX, event.clientY);
}

function showPopup(x, y){
    var popup = document.getElementById("popup");
    popup.style.left = x + "px";
    popup.style.top = y + "px";
    popup.className = "reveal";
}




       Avoid global functions and variables
var Controller = {
    handleClick: function(event){
        this.showPopup(event.clientX, event.clientY);
    },

     showPopup: function (x, y){
         var popup = document.getElementById("popup");
         popup.style.left = x + "px";
         popup.style.top = y + "px";
         popup.className = "reveal";
     }
};




        Avoid global functions and variables
      Create a single global (if necessary) and attach everything to it
var Controller = {
    addClass: function(element, className){
        element.className += " " + className;
    }
};




                Throw your own errors
                 When you know a function will fail
var Controller = {
    addClass: function(element, className){
        if (!element) {
            throw new Error("addClass: 1st argument missing.");
        }
        element.className += " " + className;
    }
};




                Throw your own errors
                 When you know a function will fail
var Controller = {
    process: function(items){
        if (items != null){
            items.sort();
            items.forEach(function(item){
                //do something
            });
        }
    }
};




                Avoid null comparisons
var Controller = {
    process: function(items){
        if (items instanceof Array){
            items.sort();
            items.forEach(function(item){
                //do something
            });
        }
    }
};




                 Avoid null comparisons
         Test for precisely what you want to know if it matters
Avoid null comparisons
• Use instanceof to test for specific object
  types
   – object instanceof MyType
• Use typeof to test for primitive types
  – typeof value == "string"
  – BEWARE: typeof null == "object"
function validate(value) {
    if (!value) {
        alert("Invalid value");
        location.href = "/errors/invalid.php";
    }
}




              Separate config data
var config = {
    urls: {
        invalid: "/errors/invalid.php"
    },
    strs: {
        invalidmsg: "Invalid value"
    }
};


function validate(value) {
    if (!value) {
        alert(config.strs.invalidmsg);
        location.href = config.urls.invalid;
    }
}


                    Separate config data
Separate Config Data
• All URLs needed by the JavaScript
• Any strings that are displayed to the user
• Any HTML that needs to be created from
  JavaScript
• Settings (i.e., items per page)
• Repeated unique values
• Any value that may change in the future
Build Process


                Understandable


                           Testable
Build Process




   Build
Build
 Add/Remove              Validate
  Debugging               Code

 Concatenate
                        Minify Files
    Files

  Generate                Deploy
Documentation              Files
Build



Development   Testing   Deployment
Recommendations
• One object or object definition per file
  – Track dependencies
• Use a build process to combines files
  – Determines correct order
  – Validates code (JSHint)
  – Minifies code (YUI Compressor)
  – Generate documentation (YUI Doc)
http://www.julienlecomte.net/blog/2007/09/16/
Recap
Remember
• Code conventions ensure everyone's speaking
  the same language
• Loose coupling of layers make changes and
  debugging easier
• Good programming practices allow you to
• Code organization and a build process help to
  bring sanity to an otherwise crazy process
Questions?
Etcetera
• My blog:      www.nczonline.net
• Twitter:      @slicknet
• These Slides: slideshare.net/nzakas

More Related Content

PDF
Scalable JavaScript Application Architecture
PPTX
JavaScript APIs you’ve never heard of (and some you have)
PDF
JavaScript and UI Architecture Best Practices
PDF
JavaScript Best Pratices
PDF
Basic Tutorial of React for Programmers
PDF
JavaScript - From Birth To Closure
PDF
Even more java script best practices
PDF
ES3-2020-P3 TDD Calculator
Scalable JavaScript Application Architecture
JavaScript APIs you’ve never heard of (and some you have)
JavaScript and UI Architecture Best Practices
JavaScript Best Pratices
Basic Tutorial of React for Programmers
JavaScript - From Birth To Closure
Even more java script best practices
ES3-2020-P3 TDD Calculator

What's hot (20)

PDF
JS and patterns
PPT
The Theory Of The Dom
PDF
JavaScript Library Overview
PDF
Maintainable JavaScript
PDF
Redux for ReactJS Programmers
PDF
Understanding Asynchronous JavaScript
PPTX
5 Tips for Better JavaScript
PPTX
Javascript basics for automation testing
PPT
Ajax Performance
PDF
Advanced javascript
PDF
Secrets of JavaScript Libraries
PPT
Advanced JavaScript
PPT
Retrofitting
PDF
ReactJS for Programmers
PDF
Performance Optimization and JavaScript Best Practices
PDF
Ten useful JavaScript tips & best practices
PDF
Android programming -_pushing_the_limits
PDF
JavaScript Patterns
PPTX
PDF
JavaScript in 2016
JS and patterns
The Theory Of The Dom
JavaScript Library Overview
Maintainable JavaScript
Redux for ReactJS Programmers
Understanding Asynchronous JavaScript
5 Tips for Better JavaScript
Javascript basics for automation testing
Ajax Performance
Advanced javascript
Secrets of JavaScript Libraries
Advanced JavaScript
Retrofitting
ReactJS for Programmers
Performance Optimization and JavaScript Best Practices
Ten useful JavaScript tips & best practices
Android programming -_pushing_the_limits
JavaScript Patterns
JavaScript in 2016
Ad

Viewers also liked (20)

PDF
High Performance JavaScript 2011
PDF
Efficient JavaScript Unit Testing, May 2012
PDF
Test your Javascript! v1.1
PPTX
Test-Driven JavaScript Development (JavaZone 2010)
KEY
Agile JavaScript Testing
PDF
AngularJS Deep Dives (NYC GDG Apr 2013)
PPTX
Maintainable JavaScript 2012
PDF
Enterprise JavaScript Error Handling (Ajax Experience 2008)
PPTX
Browser Wars Episode 1: The Phantom Menace
PDF
The Art of AngularJS - DeRailed 2014
PDF
High Performance JavaScript (YUIConf 2010)
PDF
High Performance JavaScript - Fronteers 2010
PPTX
Becoming Node.js ninja on Cloud Foundry
PPTX
Scalable JavaScript Application Architecture 2012
KEY
Meteor 0.3.6 Preview
PDF
제2회 hello world 오픈세미나 hello world-raphael차트
PDF
다이내믹 스타일시트 언어 Less framework 활용 by yamoo9
PDF
Haml And Sass In 15 Minutes
KEY
Groovy overview, DSLs and ecosystem - Mars JUG - 2010
PPTX
Testing nodejs apps
High Performance JavaScript 2011
Efficient JavaScript Unit Testing, May 2012
Test your Javascript! v1.1
Test-Driven JavaScript Development (JavaZone 2010)
Agile JavaScript Testing
AngularJS Deep Dives (NYC GDG Apr 2013)
Maintainable JavaScript 2012
Enterprise JavaScript Error Handling (Ajax Experience 2008)
Browser Wars Episode 1: The Phantom Menace
The Art of AngularJS - DeRailed 2014
High Performance JavaScript (YUIConf 2010)
High Performance JavaScript - Fronteers 2010
Becoming Node.js ninja on Cloud Foundry
Scalable JavaScript Application Architecture 2012
Meteor 0.3.6 Preview
제2회 hello world 오픈세미나 hello world-raphael차트
다이내믹 스타일시트 언어 Less framework 활용 by yamoo9
Haml And Sass In 15 Minutes
Groovy overview, DSLs and ecosystem - Mars JUG - 2010
Testing nodejs apps
Ad

Similar to Maintainable JavaScript 2011 (20)

PDF
Javascript Design Patterns
PPTX
jQuery Data Manipulate API - A source code dissecting journey
PPTX
Art of Javascript
PPTX
Taming that client side mess with Backbone.js
PPTX
Adding a modern twist to legacy web applications
PPTX
Get started with YUI
PDF
The Beauty Of Java Script V5a
PPT
Javascript Templating
PPT
Web Optimization Summit: Coding for Performance
PPTX
Javascript And J Query
PPT
Javascript Design Patterns
PDF
JavaScript Abstraction
PDF
The Beauty of Java Script
PDF
Clean Javascript
PPTX
Intro to Javascript
PDF
33rd Degree 2013, Bad Tests, Good Tests
PDF
HTML5 APIs - Where no man has gone before! - Altran
PDF
Idioms in swift 2016 05c
PDF
Flink Forward Berlin 2018: Jared Stehler - "Streaming ETL with Flink and Elas...
Javascript Design Patterns
jQuery Data Manipulate API - A source code dissecting journey
Art of Javascript
Taming that client side mess with Backbone.js
Adding a modern twist to legacy web applications
Get started with YUI
The Beauty Of Java Script V5a
Javascript Templating
Web Optimization Summit: Coding for Performance
Javascript And J Query
Javascript Design Patterns
JavaScript Abstraction
The Beauty of Java Script
Clean Javascript
Intro to Javascript
33rd Degree 2013, Bad Tests, Good Tests
HTML5 APIs - Where no man has gone before! - Altran
Idioms in swift 2016 05c
Flink Forward Berlin 2018: Jared Stehler - "Streaming ETL with Flink and Elas...

More from Nicholas Zakas (20)

PPTX
Enough with the JavaScript already!
PPTX
The Pointerless Web
PPTX
JavaScript Timers, Power Consumption, and Performance
PPTX
High Performance JavaScript (CapitolJS 2011)
PDF
Mobile Web Speed Bumps
PDF
High Performance JavaScript (Amazon DevCon 2011)
PDF
Progressive Enhancement 2.0 (Conference Agnostic)
PDF
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
PDF
YUI Test The Next Generation (YUIConf 2010)
PDF
Nicholas' Performance Talk at Google
PDF
High Performance JavaScript - WebDirections USA 2010
PDF
Performance on the Yahoo! Homepage
PDF
High Performance JavaScript - jQuery Conference SF Bay Area 2010
PPT
Responsive interfaces
PDF
Extreme JavaScript Compression With YUI Compressor
PDF
Writing Efficient JavaScript
PDF
Speed Up Your JavaScript
PDF
JavaScript Variable Performance
ODP
The New Yahoo! Homepage and YUI 3
PDF
Test Driven Development With YUI Test (Ajax Experience 2008)
Enough with the JavaScript already!
The Pointerless Web
JavaScript Timers, Power Consumption, and Performance
High Performance JavaScript (CapitolJS 2011)
Mobile Web Speed Bumps
High Performance JavaScript (Amazon DevCon 2011)
Progressive Enhancement 2.0 (Conference Agnostic)
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
YUI Test The Next Generation (YUIConf 2010)
Nicholas' Performance Talk at Google
High Performance JavaScript - WebDirections USA 2010
Performance on the Yahoo! Homepage
High Performance JavaScript - jQuery Conference SF Bay Area 2010
Responsive interfaces
Extreme JavaScript Compression With YUI Compressor
Writing Efficient JavaScript
Speed Up Your JavaScript
JavaScript Variable Performance
The New Yahoo! Homepage and YUI 3
Test Driven Development With YUI Test (Ajax Experience 2008)

Recently uploaded (20)

PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
Spectroscopy.pptx food analysis technology
PPT
Teaching material agriculture food technology
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Getting Started with Data Integration: FME Form 101
PDF
A comparative analysis of optical character recognition models for extracting...
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PPTX
1. Introduction to Computer Programming.pptx
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
Tartificialntelligence_presentation.pptx
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
Encapsulation_ Review paper, used for researhc scholars
Spectroscopy.pptx food analysis technology
Teaching material agriculture food technology
Mobile App Security Testing_ A Comprehensive Guide.pdf
Group 1 Presentation -Planning and Decision Making .pptx
Network Security Unit 5.pdf for BCA BBA.
Getting Started with Data Integration: FME Form 101
A comparative analysis of optical character recognition models for extracting...
20250228 LYD VKU AI Blended-Learning.pptx
Per capita expenditure prediction using model stacking based on satellite ima...
Building Integrated photovoltaic BIPV_UPV.pdf
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
1. Introduction to Computer Programming.pptx
MIND Revenue Release Quarter 2 2025 Press Release
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Spectral efficient network and resource selection model in 5G networks
Tartificialntelligence_presentation.pptx
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Reach Out and Touch Someone: Haptics and Empathic Computing

Maintainable JavaScript 2011

  • 1. flickr.com/photos/jontysewell/4526861658/ Maintainable JavaScript Nicholas C. Zakas | @slicknet
  • 2. Who's this guy? 5 years Co-Creator Contributor, Tech Lead, Yahoo! csslint.net Creator of YUI Test Author Lead Author Contributor Lead Author
  • 4. flickr.com/photos/indraw/4857101224/ Most of your time is spent maintaining code
  • 5. Who cares? Your Employer Your Co-workers, Present and Future
  • 6. flickr.com/photos/protestphotos1/4726566233/ We all want to be rock stars "Don't mess with my process, man! It's about the music!"
  • 7. flickr.com/photos/the_junes/3120810156/ At work, you're part of a team Awesome happens when everyone is on the same page
  • 8. Maintainable code is Understandable Adaptable Debuggable Testable Intuitive Extendable
  • 9. Code Conventions Understandable Intuitive
  • 10. flickr.com/photos/29271559@N02/5799773313/ "Programs are meant to be read by humans and only incidentally for computers to execute." Donald Knuth
  • 11. flickr.com/photos/polinasergeeva/3052378826/ Tabs for indentation 4 spaces for indentation Indentation
  • 12. if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == 'object') { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } } }
  • 13. if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == 'object') { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } } }
  • 15. /** * Returns a new object containing all of the properties of * all the supplied objects. The properties from later objects * will overwrite those in earlier objects. Passing in a * single object will create a shallow copy of it. For a deep * copy, use clone. * @method merge * @for YUI * @param arguments {Object*} the objects to merge. * @return {object} the new merged object. */ Y.merge = function() { var a = arguments, o = {}, i, l = a.length; for (i = 0; i < l; i = i + 1) { Y.mix(o, a[i], true); } return o; }; Every method
  • 16. if (mode) { switch (mode) { case 1: // proto to proto return Y.mix(r.prototype, s.prototype, ov, wl, 0, merge); case 2: // object to object and proto to proto Y.mix(r.prototype, s.prototype, ov, wl, 0, merge); break; // pass through case 3: // proto to static return Y.mix(r, s.prototype, ov, wl, 0, merge); case 4: // static to proto return Y.mix(r.prototype, s, ov, wl, 0, merge); default: // object to object is what happens below } } Difficult-to-understand code
  • 17. while (element &&(element = element[axis])){ //NOTE: assignment if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) { return element; } } Code that might seem to be wrong
  • 19. Naming • Use logical names for variables and functions – Don't worry about length • Variable names should be nouns • Function names should begin with a verb (i.e. getName()) – Functions return booleans should begin with "is", such as isValid() • Avoid useless names such as foo and temp
  • 20. if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == 'object') { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } } }
  • 21. Loose Coupling Adaptable Debuggable Extendable
  • 22. Front End Layers Presentation Behavior (CSS) (JavaScript) Base JS Data/Structure (HTML)
  • 23. Don't cross the streams
  • 25. var element = document.getElementById("container"); element.innerHTML = "<div class="popup"></div>"; Keep HTML out of JavaScript
  • 26. .foo { width: expression(document.offsetWidth + "px"); } Keep JavaScript out of CSS
  • 27. var element = document.getElementById("container"); element.style.color = "red"; element.style.cssText = "background:blue;border:1px solid red"; Keep CSS out of JavaScript
  • 28. Programming Practices Adaptable Debuggable Testable Extendable
  • 29. //the wrong way!!! function handleClick(event){ var popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal"; } Event handlers should only handle events
  • 30. //better, but still wrong function handleClick(event){ showPopup(event); } function showPopup(event){ var popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal"; } Don't pass the event object around
  • 31. //win!! function handleClick(event){ showPopup(event.clientX, event.clientY); } function showPopup(x, y){ var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal"; } Properly separated event handling
  • 32. //don't add new methods Array.prototype.awYeah = function(){ alert("Aw yeah!"); }; //don't override methods YUI.use = function(){ alert("Aw yeah!"); }; Don't modify objects you don't own If you didn't define the object yourself, you don't own it
  • 34. function handleClick(event){ showPopup(event.clientX, event.clientY); } function showPopup(x, y){ var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal"; } Avoid global functions and variables
  • 35. var Controller = { handleClick: function(event){ this.showPopup(event.clientX, event.clientY); }, showPopup: function (x, y){ var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal"; } }; Avoid global functions and variables Create a single global (if necessary) and attach everything to it
  • 36. var Controller = { addClass: function(element, className){ element.className += " " + className; } }; Throw your own errors When you know a function will fail
  • 37. var Controller = { addClass: function(element, className){ if (!element) { throw new Error("addClass: 1st argument missing."); } element.className += " " + className; } }; Throw your own errors When you know a function will fail
  • 38. var Controller = { process: function(items){ if (items != null){ items.sort(); items.forEach(function(item){ //do something }); } } }; Avoid null comparisons
  • 39. var Controller = { process: function(items){ if (items instanceof Array){ items.sort(); items.forEach(function(item){ //do something }); } } }; Avoid null comparisons Test for precisely what you want to know if it matters
  • 40. Avoid null comparisons • Use instanceof to test for specific object types – object instanceof MyType • Use typeof to test for primitive types – typeof value == "string" – BEWARE: typeof null == "object"
  • 41. function validate(value) { if (!value) { alert("Invalid value"); location.href = "/errors/invalid.php"; } } Separate config data
  • 42. var config = { urls: { invalid: "/errors/invalid.php" }, strs: { invalidmsg: "Invalid value" } }; function validate(value) { if (!value) { alert(config.strs.invalidmsg); location.href = config.urls.invalid; } } Separate config data
  • 43. Separate Config Data • All URLs needed by the JavaScript • Any strings that are displayed to the user • Any HTML that needs to be created from JavaScript • Settings (i.e., items per page) • Repeated unique values • Any value that may change in the future
  • 44. Build Process Understandable Testable
  • 45. Build Process Build
  • 46. Build Add/Remove Validate Debugging Code Concatenate Minify Files Files Generate Deploy Documentation Files
  • 47. Build Development Testing Deployment
  • 48. Recommendations • One object or object definition per file – Track dependencies • Use a build process to combines files – Determines correct order – Validates code (JSHint) – Minifies code (YUI Compressor) – Generate documentation (YUI Doc)
  • 50. Recap
  • 51. Remember • Code conventions ensure everyone's speaking the same language • Loose coupling of layers make changes and debugging easier • Good programming practices allow you to • Code organization and a build process help to bring sanity to an otherwise crazy process
  • 53. Etcetera • My blog: www.nczonline.net • Twitter: @slicknet • These Slides: slideshare.net/nzakas