Responsible JavaScript
    Refresh NYC — January 2010




                                 1
Where should I get started?
 •   Globals          •   switch () {...}

 •   Namespaces       •   Equality

 •   Prototypes...
Globals



          http://www.lovemikeg.com/blog/2010/01/19/responsible-javascript-globals/
                            ...
Globals have a bad
reputation.


                     4
Where possible, just
avoid them.


                       5
(function () {

  var printMe;

  printMe = document.getElementById(‘print-me’);
  printMe.addEventListener(‘click’, funct...
In all other cases,
simply don’t pollute.


                        7
Rules for Responsible Globals


Namespace everything.
Only one global per library.
Only one global per application.




  ...
Good libraries...


When choosing a library, choose a responsible
one.
   •   jQuery w/compatibility mode is great

   •  ...
Good applications...

Keep it simple: each app gets a global
In most cases, a site == an app
In other cases, a page == an ...
Namespaces



       http://www.lovemikeg.com/blog/2010/01/20/responsible-javascript-namespaces/
                         ...
Namespaces are a
really good idea.


                    12
jQuery.ajax(…)



                 13
Namespaces can get
out of control. Fast.


                        14
com.foo.utils.appManager
  .myApp.widgets
  .contactForm.validate();




                             15
Responsible Namespaces

Use a namespace creator function
Segregate application namespaces from library
namespaces
Organize...
This might seem like a good
idea…


      var myNS = { … };



   …until you have multiple
     modules in myNS.
         ...
How do you do this reliably?


  myNS.myModule = { … };




                               18
How do you do this reliably?


var myNS = window.myNS || {};
myNS.myModule = {};




                                19
This is a better idea:


   foo.namespace(‘myNS.myModule’);




                                     20
Applications vs. Libraries

Applications are living, breathing structures
which must be accepting to change both
internall...
In other words...

You application will be a self-contained entity
which is made up of lots of smaller
components.
   •   ...
Prototypes



      http://www.lovemikeg.com/blog/2010/01/21/responsible-javascript-prototype-modification/
               ...
Prototypes are
powerful.
Really powerful.


                   24
“With great power there must
also come… great responsibility!”
  — Amazing Fantasy #15 (The first Spider-Man story)




   ...
“Yeah, but I want convenience.”

Array.prototype.each = function (callback) {
    for (var i = 0, l = this.length; i < l; ...
Think it through…


Is it proper to cast your dependencies on the
language itself?
How/Where is this documented? Is it obv...
How many members in foo?
Object.prototype.count = function () {
    var count = 0;
    for (var i in this) count++;
    re...
Go ahead. Say it.


“But you should be using Object.hasOwnProperty.”
   •   Yeah but does anyone actually do that?

   •  ...
A better option is to
simply extend.


                        30
var MyArray = function () {};
MyArray.prototype = new Array;




                                 31
Factories



            http://www.lovemikeg.com/blog/2010/01/22/responsible-javascript-using-factories/
                ...
Factories are your
friends.


                     33
Factories manage complexity.


…and anything that reduces complexity should
be considered a best practice right?
Factories...
Factories are a safety measure.

 var Person = function (name, location) {
     this.name = name;
     this.location = loc...
Constructors are simply
broken.

Forgetting the new keyword can be disastrous.
Best case scenario, a few globals spill out...
Problem solved.

Person.factory = function (name, location) {
  return new Person(name, location);
}

var mike = new Perso...
this


       http://www.lovemikeg.com/blog/2010/01/23/responsible-javascript-using-this/
                                ...
this  has an identity
crisis.


                        39
var foo = {
  ‘bar’ : 12345,

     ‘getBar’ : function () {
        return this.bar;
     },

     ‘onclickCallback’ : fun...
this is ambiguous

It refers to the object in which its defined.
Unless:
   •   It’s copied (referenced) to another object
...
Best practices

Know your namespace. Be explicit.
Fix your events.You can never be too sure.
Keep your event handlers in a...
Incrementing &
Decrementing


                 43
++ and -- have a bad
reputation… to some.


                       44
“The ++ (increment) and -- (decrement) operators
have been known to contribute to bad code by
encouraging excessive tricki...
Trickiness like...
var a = 1;
var b = 2;
var c = 3;

console.log(a++ + b == c);
console.log(a + ++b == c);
console.log(a +...
Suggestions


Don’t write tricky code like that.
   •   Probably your best bet ;)
Don’t use incrementors/decrementors
   •...
switch () {...}



                  48
switch can break if
you don’t break.


                      49
function dateSuffix(date) {
    switch (date){
        case (1) : case (21) : case (31):
            dt = "st";
          ...
… is the same as…



                    51
function betterDateSuffix (date) {
    if (date === 1 || date === 21 || date === 31) {
        return date + 'st';
    }
 ...
and …



        53
function yetAnotherDateSuffix   (date) {
    var suffixMap = {
        'st' : (date === 1 ||   date === 21 || date === 31)...
Which is better?

Depends on your team’s coding standards.
I suggest:
   •   The one which is easiest to understand.

   •...
Equality



           56
Equality isn’t as easy as
you think.


                            57
Take your best guess
console.log(false   ==   -1);
console.log(false   ==   -0);
console.log(false   ==   0);
console.log(...
Take your best guess
console.log(false   ==   -1);          //   false
console.log(false   ==   -0);          //   true
co...
Just use === or !==


Your code will be less ambiguous
Your code will run faster
   •   No need to convert types




     ...
$



    61
Developers love $.



                     62
The problem, is that everyone
loves $.

Brought to you by Prototype
Made famous by jQuery


But what happens if you includ...
The Specs say...



“$ is reserved for implementations”
   •   Whatever that means.




                                  ...
Fact: $ is perfectly valid.



                              65
“Just don’t do that.”


Yeah. Easier said than done.
   •   Try talking your client its better to rewrite the
       widge...
Just don’t be irresponsible.


Give your devs a choice to use it or not
Never write applications that assume $
Always assu...
There is hope.

jQuery has compatability mode.
   •   Please use it.

   •   Develop your apps as if you’re writing a plug...
Thank you.
mikeg@lovemikeg.com




                      69
Upcoming SlideShare
Loading in …5
×

Responsible JavaScript

1,933 views

Published on

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

  • Be the first to like this

No Downloads
Views
Total views
1,933
On SlideShare
0
From Embeds
0
Number of Embeds
25
Actions
Shares
0
Downloads
18
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Responsible JavaScript

  1. 1. Responsible JavaScript Refresh NYC — January 2010 1
  2. 2. Where should I get started? • Globals • switch () {...} • Namespaces • Equality • Prototypes • $ • Factories • this • Incrementing & Decrementing 2
  3. 3. Globals http://www.lovemikeg.com/blog/2010/01/19/responsible-javascript-globals/ 3
  4. 4. Globals have a bad reputation. 4
  5. 5. Where possible, just avoid them. 5
  6. 6. (function () { var printMe; printMe = document.getElementById(‘print-me’); printMe.addEventListener(‘click’, function () { window.print(); return false; }, false); })(); 6
  7. 7. In all other cases, simply don’t pollute. 7
  8. 8. Rules for Responsible Globals Namespace everything. Only one global per library. Only one global per application. 8
  9. 9. Good libraries... When choosing a library, choose a responsible one. • jQuery w/compatibility mode is great • YUI is also a great choice 9
  10. 10. Good applications... Keep it simple: each app gets a global In most cases, a site == an app In other cases, a page == an app • searchResults • userProfile • shoppingCart 10
  11. 11. Namespaces http://www.lovemikeg.com/blog/2010/01/20/responsible-javascript-namespaces/ 11
  12. 12. Namespaces are a really good idea. 12
  13. 13. jQuery.ajax(…) 13
  14. 14. Namespaces can get out of control. Fast. 14
  15. 15. com.foo.utils.appManager .myApp.widgets .contactForm.validate(); 15
  16. 16. Responsible Namespaces Use a namespace creator function Segregate application namespaces from library namespaces Organize libraries into component groups Organize applications into functional groups 16
  17. 17. This might seem like a good idea… var myNS = { … }; …until you have multiple modules in myNS. 17
  18. 18. How do you do this reliably? myNS.myModule = { … }; 18
  19. 19. How do you do this reliably? var myNS = window.myNS || {}; myNS.myModule = {}; 19
  20. 20. This is a better idea: foo.namespace(‘myNS.myModule’); 20
  21. 21. Applications vs. Libraries Applications are living, breathing structures which must be accepting to change both internally and externally. Libraries are shared dependencies and must be be organized in a stable structure so as to minimize the need for change at all. 21
  22. 22. In other words... You application will be a self-contained entity which is made up of lots of smaller components. • Don’t be strict and rigid with your app namespaces. • References to other apps are common, keep app namespaces shallow. 22
  23. 23. Prototypes http://www.lovemikeg.com/blog/2010/01/21/responsible-javascript-prototype-modification/ 23
  24. 24. Prototypes are powerful. Really powerful. 24
  25. 25. “With great power there must also come… great responsibility!” — Amazing Fantasy #15 (The first Spider-Man story) 25
  26. 26. “Yeah, but I want convenience.” Array.prototype.each = function (callback) { for (var i = 0, l = this.length; i < l; i++) { callback(this[i], i); } }; 26
  27. 27. Think it through… Is it proper to cast your dependencies on the language itself? How/Where is this documented? Is it obvious to your team? Are there any other unintended consequences? 27
  28. 28. How many members in foo? Object.prototype.count = function () { var count = 0; for (var i in this) count++; return count; }; console.log( {'foo':12345}.count() ); 28
  29. 29. Go ahead. Say it. “But you should be using Object.hasOwnProperty.” • Yeah but does anyone actually do that? • Do you feel comfortable assuming that all future developers on your project will know that? 29
  30. 30. A better option is to simply extend. 30
  31. 31. var MyArray = function () {}; MyArray.prototype = new Array; 31
  32. 32. Factories http://www.lovemikeg.com/blog/2010/01/22/responsible-javascript-using-factories/ 32
  33. 33. Factories are your friends. 33
  34. 34. Factories manage complexity. …and anything that reduces complexity should be considered a best practice right? Factories can also: • Make your code safer • Make your code faster 34
  35. 35. Factories are a safety measure. var Person = function (name, location) { this.name = name; this.location = location; }; var mike = new Person('Mike G.', 'NYC'); var alex = Person('Alex H.', 'NYC'); // oops! 35
  36. 36. Constructors are simply broken. Forgetting the new keyword can be disastrous. Best case scenario, a few globals spill out. Worst case scenario, your app stops working. 36
  37. 37. Problem solved. Person.factory = function (name, location) { return new Person(name, location); } var mike = new Person.factory('Mike G.', 'NYC'); var alex = Person.factory('Alex H.', 'NYC'); 37
  38. 38. this http://www.lovemikeg.com/blog/2010/01/23/responsible-javascript-using-this/ 38
  39. 39. this has an identity crisis. 39
  40. 40. var foo = { ‘bar’ : 12345, ‘getBar’ : function () { return this.bar; }, ‘onclickCallback’ : function () { window.open(this.href); return false; }, ‘wtf’ : function () { return { ‘hello’ : ‘world’, ‘sayHi’ : function () { return this.hello; } }; } }; 40
  41. 41. this is ambiguous It refers to the object in which its defined. Unless: • It’s copied (referenced) to another object • It’s used as an event handler (sometimes). • You .call or .apply it. 41
  42. 42. Best practices Know your namespace. Be explicit. Fix your events.You can never be too sure. Keep your event handlers in a separate object. Document all irregularities (including event handlers). 42
  43. 43. Incrementing & Decrementing 43
  44. 44. ++ and -- have a bad reputation… to some. 44
  45. 45. “The ++ (increment) and -- (decrement) operators have been known to contribute to bad code by encouraging excessive trickiness. They are second only to faulty architecture in enabling to viruses and other security menaces.” —Douglas Crockford http://www.jslint.com/lint.html#inc 45
  46. 46. Trickiness like... var a = 1; var b = 2; var c = 3; console.log(a++ + b == c); console.log(a + ++b == c); console.log(a + + + b == c); console.log(a, b, c); 46
  47. 47. Suggestions Don’t write tricky code like that. • Probably your best bet ;) Don’t use incrementors/decrementors • There’s nothing wrong with += 1 47
  48. 48. switch () {...} 48
  49. 49. switch can break if you don’t break. 49
  50. 50. function dateSuffix(date) { switch (date){ case (1) : case (21) : case (31): dt = "st"; break; case (2) : case (22): dt = "nd"; break; case (3) : case (23): dt = "rd"; break; default: dt = "th"; } return date + suffix; } 50
  51. 51. … is the same as… 51
  52. 52. function betterDateSuffix (date) { if (date === 1 || date === 21 || date === 31) { return date + 'st'; } else if (date === 2 || date === 22) { return date + 'nd'; } else if (date === 3 || date === 23) { return date + rd; } else { return date + 'th'; } return date + suffix; } 52
  53. 53. and … 53
  54. 54. function yetAnotherDateSuffix (date) { var suffixMap = { 'st' : (date === 1 || date === 21 || date === 31), 'nd' : (date === 2 || date === 22), 'rd' : (date === 3 || date === 23), 'th' : true }; for (var suffix in suffixMap) { if (suffixMap[suffix]) { return date + suffix; } } } 54
  55. 55. Which is better? Depends on your team’s coding standards. I suggest: • The one which is easiest to understand. • The one which is easiest to change. (I like the third option, personally.) 55
  56. 56. Equality 56
  57. 57. Equality isn’t as easy as you think. 57
  58. 58. Take your best guess console.log(false == -1); console.log(false == -0); console.log(false == 0); console.log(false == []); console.log(false == ""); console.log(false == "0"); console.log(false == null); console.log(false == undefined); console.log(false == null); 58
  59. 59. Take your best guess console.log(false == -1); // false console.log(false == -0); // true console.log(false == 0); // true console.log(false == []); // true console.log(false == ""); // true console.log(false == "0"); // true console.log(false == null); // false console.log(false == undefined); // false console.log(false == null); // false 59
  60. 60. Just use === or !== Your code will be less ambiguous Your code will run faster • No need to convert types 60
  61. 61. $ 61
  62. 62. Developers love $. 62
  63. 63. The problem, is that everyone loves $. Brought to you by Prototype Made famous by jQuery But what happens if you include jQuery and Prototype on the same page? 63
  64. 64. The Specs say... “$ is reserved for implementations” • Whatever that means. 64
  65. 65. Fact: $ is perfectly valid. 65
  66. 66. “Just don’t do that.” Yeah. Easier said than done. • Try talking your client its better to rewrite the widget written in another library • They like their $$ too. 66
  67. 67. Just don’t be irresponsible. Give your devs a choice to use it or not Never write applications that assume $ Always assume control over $ 67
  68. 68. There is hope. jQuery has compatability mode. • Please use it. • Develop your apps as if you’re writing a plugin… var myApp = (function ($) { // Your code goes here. })(window.jQuery); YUI is a nice choice too ;) 68
  69. 69. Thank you. mikeg@lovemikeg.com 69

×