SlideShare a Scribd company logo
JavaScript Patterns




    Giordano Scalzo
Wednesday, November 10, 2010
I’m not a guru!




Wednesday, November 10, 2010
I’m still learning




Wednesday, November 10, 2010
Why?




Wednesday, November 10, 2010
JavaScript isn’t this anymore




Wednesday, November 10, 2010
JavaScript is everywhere!




Wednesday, November 10, 2010
JavaScript is trendy!


            Technology Radar




Wednesday, November 10, 2010
JavaScript is trendy!


            Technology Radar




Wednesday, November 10, 2010
At the beginning...




Wednesday, November 10, 2010
Hacked by Brendan Eich in one week...




Wednesday, November 10, 2010
Former Mocha, renamed to JavaScript by Netscape




Wednesday, November 10, 2010
after a while...




Wednesday, November 10, 2010
and...




Wednesday, November 10, 2010
:-(




Wednesday, November 10, 2010
and so...




Wednesday, November 10, 2010
Back to study!




Wednesday, November 10, 2010
Started a notebook...




Wednesday, November 10, 2010
Essential
                                  Scope




Wednesday, November 10, 2010
function sum(x, y){
                                   // implied global
                                   result = x + y;
                                   return result;
                               }




{antipattern}
Wednesday, November 10, 2010
Global variables are evil!




Wednesday, November 10, 2010
Variables clash




Wednesday, November 10, 2010
Always declare variables with var



                                      function sum(x, y){
                                      	 var result = x + y;
                                         return result;
                                      }




{pattern}
Wednesday, November 10, 2010
function foo(){
                                   var a = b = 0;
                                   //...
                               }




{antipattern}
Wednesday, November 10, 2010
b become global




                               function foo(){
                                   var a = (b = 0);
                                   //...
                               }




{antipattern}
Wednesday, November 10, 2010
don’t use assign chain in definition




                               function foo(){
                                   var a, b;
                                   a = b = 0;
                                   //...
                               }




{pattern}
Wednesday, November 10, 2010
Single var pattern


                                function func(){
                                    var a = 1,
                                  	 b = 2,
                                  	 sum = a + b,
                                  	 myobject = {},
                                  	 i,
                                  	 j;
                                    // function body...
                                }




{pattern}
Wednesday, November 10, 2010
Don’t forget comma otherwise...




Wednesday, November 10, 2010
... variables become globals




Wednesday, November 10, 2010
Hoisting


                               myname = "global"; // global variable
                               function func(){
                               	 // code...
                                   console.log(myname); // "undefined"

                                   // code...
                                   var myname = "local";
                                   console.log(myname); // "local"
                               }

                               func();




{antipattern}
Wednesday, November 10, 2010
Hoisting


                               myname = "global"; // global variable
                               function func(){
                                   var myname = "declared";
                               	 // code...
                                   console.log(myname); // "declared"

                                   // code...
                                   myname = "local";
                                   console.log(myname); // "local"
                               }

                               func();




{pattern}
Wednesday, November 10, 2010
Against minimum vertical distance
                               principle


              “Variables should be declared as close to
              their usage as possible”
                                Robert C. Martin - Clean Code



Wednesday, November 10, 2010
Essential
                               Literal and Constructor




Wednesday, November 10, 2010
In JavaScript almost everything is an object




Wednesday, November 10, 2010
It’s easy...



                               var person = new Object();
                               person.name = "Scott";
                               person.say = function(){
                                   return "I am " + this.name;
                               };

                               console.log(person.say());




Wednesday, November 10, 2010
but wrong! :-(



                               var person = new Object();
                               person.name = "Scott";
                               person.say = function(){
                                   return "I am " + this.name;
                               };

                               console.log(person.say());




{antipattern}
Wednesday, November 10, 2010
var person = {};
                               person.name = "Scott";
                               person.say = function(){
                                   return "I am " + this.name;
                               };

                               console.log(person.say());




{pattern}
Wednesday, November 10, 2010
What if we need similar objects...

                          var person = {};
                          person.name = "Scott";
                          person.say = function(){
                              return "I am " + this.name;
                          };
                          console.log(person.say()); // I am Scott

                          var otherPerson = {};
                          otherPerson.name = "Tiger";
                          otherPerson.say = function(){
                              return "I am " + this.name;
                          };

                          console.log(otherPerson.say()); // I am Tiger




Wednesday, November 10, 2010
A lot of duplication

                          var person = {};
                          person.name = "Scott";
                          person.say = function(){
                              return "I am " + this.name;
                          };
                          console.log(person.say()); // I am Scott

                          var otherPerson = {};
                          otherPerson.name = "Tiger";
                          otherPerson.say = function(){
                              return "I am " + this.name;
                          };

                          console.log(otherPerson.say()); // I am Tiger




Wednesday, November 10, 2010
Duplication is evil!




Wednesday, November 10, 2010
Custom Constructor Functions



                               var Person = function(name){
                                   this.name = name;
                                   this.say = function(){
                                       return "I am " + this.name;
                                   }
                               }
                               var person = new Person("Scott");

                               console.log(person.say()); // I am Scott




{pattern}
Wednesday, November 10, 2010
Behind the scenes...



                               var Person = function(name){
                                   // var this = {};
                                   this.name = name;
                                   this.say = function(){
                                       return "I am " + this.name;
                                   };
                                   // return this;
                               };




{pattern}
Wednesday, November 10, 2010
So, at the end...

                               var Person = function(name){
                                   this.name = name;
                                   this.say = function(){
                                       return "I am " + this.name;
                                   };
                               };

                               var scott = new Person('Scott');
                               var tiger = new Person('Tiger');

                               console.log(scott.say());
                               console.log(tiger.say());




{pattern}
Wednesday, November 10, 2010
What if we forget new?




Wednesday, November 10, 2010
this will point to global object

                           var Person = function(name){
                               this.name = name;
                               this.say = function(){
                                   return "I am " + this.name;
                               };
                           };

                           var scott = new Person('Scott')
                           var adam = Person('Adam')

                           console.log(typeof scott); //object
                           console.log(scott.name); // Scott
                           console.log(typeof adam); //'undefined'
                           console.log(window.name); // Adam




Wednesday, November 10, 2010
Enforce new pattern one: naming convention




Wednesday, November 10, 2010
var Person = function(name){
                                   var that = {};
                                   that.name = name;
                                   that.say = function(){
                                       return "I am " + that.name;};
                                   return that;
                               };

                               var scott = new Person('Scott')
                               var adam = Person('Adam')

                               console.log(typeof scott); //Object
                               console.log(scott.name); // Scott

                               console.log(typeof adam); //Object
                               console.log(adam.name); // Adam



{pattern}
Wednesday, November 10, 2010
Drawback: we loose prototype reference :-(

                          var Person = function(name){
                              var that = {};
                              that.name = name;
                              that.say = function(){
                                  return "I am " + that.name;
                              };
                              return that;
                          };

                          Person.prototype.iamhumanbeing = true;

                          var scott = new Person('Scott')
                          var adam = Person('Adam')

                          console.log(scott.iamhumanbeing); // undefined
                          console.log(adam.iamhumanbeing); // undefined




Wednesday, November 10, 2010
Interm!zo

                                Prototype property




Wednesday, November 10, 2010
Define ancestors chain




                               var foo = {one: 1, two: 2};
                               var bar = {three: 3};
                               foo.__proto__ = bar;
                               console.log(foo.one);
                               console.log(foo.three);




Wednesday, November 10, 2010
bar
                                        three: 3



                                foo
                               one: 1
                               two: 2
                      __proto__

Wednesday, November 10, 2010
Behind the scenes...



                          var Person = function(name){
                              // this.prototype = {constructor: this}
                              var that = {};
                              that.name = name;
                              that.say = function(){
                                  return "I am " + that.name;
                              };
                              return that;
                          };




Wednesday, November 10, 2010
Self invoking constructor
                               var Person = function(name){
                                   if (this instanceof Person) {
                                       this.name = name;
                                       this.say = function(){
                                           return "I am " + that.name;
                                       }
                                   }
                                   else {
                                       return new Person(name);
                                   }
                               };
                               Person.prototype.iamhumanbeing = true;
                               var scott = new Person('Scott')
                               var adam = Person('Adam')
                               console.log(scott.name); // Scott
                               console.log(adam.name); // Adam
                               console.log(scott.iamhumanbeing); // true
                               console.log(adam.iamhumanbeing); // true


{pattern}
Wednesday, November 10, 2010
Essential
                                  Functions




Wednesday, November 10, 2010
Functions as first class objects




Wednesday, November 10, 2010
Immediate functions




                                (function(){
                                    alert('watch out!');
                                })();




Wednesday, November 10, 2010
Initialization pattern




                               (function(){
                                   var days = ['Sun', 'Mon', 'Tue', 'Wed',
                               	              'Thu', 'Fri', 'Sat'],
                               	     today = new Date(),
                               	 	 msg = 'Today is ' +
                               	 	        days[today.getDay()] +
                               	 	 	    ', ' +
                               	 	 	    today.getDate();
                                   console.log(msg);
                               })(); // "Today is Wed, 10"




{pattern}
Wednesday, November 10, 2010
Function scope




Wednesday, November 10, 2010
5 globals...
                               // constructors
                               function Parent(){
                               }

                               function Child(){
                               }

                               // a variable
                               var some_var = 1;
                               // some objects
                               var module1 = {};
                               module1.data = {
                                   a: 1,
                                   b: 2
                               };
                               var module2 = {};



{antipattern}
Wednesday, November 10, 2010
1 global!
                         // global object
                         var MYAPP = (function(){
                             var my = {};
                                                           {pattern}
                             // constructors
                             my.Parent = function(){};
                             my.Child = function(){};
                             // a variable
                             my.some_var = 1;
                             // an object container
                             my.modules = {};
                             // nested objects
                             my.modules.module1 = {};
                             my.modules.module1.data = {
                                 a: 1,
                                 b: 2
                             };
                             my.modules.module2 = {};
                             return my;
                         })();

                         console.log(MYAPP.modules.module1.data.a); // 1

Wednesday, November 10, 2010
What about encapsulation?




Wednesday, November 10, 2010
function Gadget(){
                       this.name = 'iPod';
                       this.stretch = function(){
                           return 'iPad';
                       }
                   };

                   var toy = new Gadget();
                   console.log(toy.name); // `iPod`
                   toy.name = 'Zune'
                   console.log(toy.name); // `Zune` is public
                   console.log(toy.stretch()); // stretch() is public




{antipattern}
Wednesday, November 10, 2010
Create private member


                               function Gadget(){
                                   var name = 'iPod';
                                   this.getName = function(){
                                       return name;
                                   }
                               };

                               var toy = new Gadget();
                               console.log(toy.getName()); // `iPod`
                               toy.name = 'Zune'
                               console.log(toy.getName()); // `iPod`




{pattern}
Wednesday, November 10, 2010
for methods too
                               function Gadget() {
                                   var name = 'iPod';
                                   var upgrade = function(){
                                       return 'iPhone';
                                   }

                                    this.getName = function () {
                                        return name;
                                    }
                                    this.pay = function() {
                                        return upgrade();
                                    }
                               };

                               var toy = new Gadget();
                               console.log(toy.pay()); // `iPhone`
                               console.log(toy.upgrade()); // `error`



{pattern}
Wednesday, November 10, 2010
Advanced
                               Code reuse patterns




Wednesday, November 10, 2010
Classical vs prototypal inheritance




                                             vs

Wednesday, November 10, 2010
Classical inheritance
                               function Parent(name){
                                   this.name = name;
                               };

                               Parent.prototype.say = function(){
                                   return 'My name is ' + this.name;
                               };

                               function Child(name){
                                   this.name = name;
                               };

                               inherit(Child, Parent);

                               var dad = new Parent('Larry');
                               var kid = new Child('Scott');

                               console.log(dad.say()); // 'My name is Larry'
                               console.log(kid.say()); // 'My name is Scott'


Wednesday, November 10, 2010
function(){
                                                  return 'My name is ' + this.name;
                                              };
                                                        Parent.prototype
                                                             say()




                               new Parent()
                                name: Larry
                                __proto__


                                      console.log(dad.say());


Wednesday, November 10, 2010
Default Classical Inheritance pattern




                                      function inherit(C, P) {
                                          C.prototype = new P();
                                      };




Wednesday, November 10, 2010
function(){
                                           return 'My name is ' + this.name;
                                       };
                                                 Parent.prototype
                                                      say()




                                            new Parent()
                    new Child()              name: Larry
                    name: Scott              __proto__
                    __proto__

             console.log(kid.say());
Wednesday, November 10, 2010
Drawback: it doesn’t call parent constructor
                               function Parent(name){
                                   this.name = name;
                               };

                               Parent.prototype.say = function(){
                                   return 'My name is ' + this.name;
                               };

                               function Child(name){
                                   this.name = name;
                               };

                               inherit(Child, Parent);

                               var dad = new Parent('Larry');
                               var kid = new Child('Scott');

                               console.log(dad.say()); // 'My name is Larry'
                               console.log(kid.say()); // 'My name is Scott'


Wednesday, November 10, 2010
Drawback: it doesn’t call parent constructor
                     function Parent(name){
                         this.name = name;
                     };

                     Parent.prototype.say = function(){
                         return 'My name is ' + this.name;
                     };

                     function Child(name){ };

                     function inherit(C, P) {
                         C.prototype = new P();
                     };

                     inherit(Child, Parent);

                     var kid = new Child('Scott');

                     console.log(kid.say()); // 'My name is undefined'


Wednesday, November 10, 2010
Pattern Extension: rent a constructor




                               function Child(name){
                                   Parent.apply(this, arguments);
                               };




Wednesday, November 10, 2010
Pattern Extension: rent a constructor
                       function Parent(name){
                           this.name = name;
                       };
                       Parent.prototype.say = function(){
                           return 'My name is ' + this.name;
                       };

                       function Child(name){
                           Parent.apply(this, arguments);
                       };

                       function inherit(C, P){
                           C.prototype = new P();
                       };
                       inherit(Child, Parent);
                       var dad = new Parent('Larry');
                       var kid = new Child('Scott');
                       console.log(dad.say()); // 'My name is Larry'
                       console.log(kid.say()); // 'My name is Scott'

Wednesday, November 10, 2010
Drawback: parent constructor is called twice
                       function Parent(name){
                           this.name = name;
                       };
                       Parent.prototype.say = function(){
                           return 'My name is ' + this.name;
                       };

                       function Child(name){
                           Parent.apply(this, arguments);
                       };

                       function inherit(C, P){
                           C.prototype = new P();
                       };
                       inherit(Child, Parent);
                       var dad = new Parent('Larry');
                       var kid = new Child('Scott');
                       console.log(dad.say()); // 'My name is Larry'
                       console.log(kid.say()); // 'My name is Scott'

Wednesday, November 10, 2010
Drawback: parent constructor is called twice
                       function Parent(name){
                           this.name = name;
                       };
                       Parent.prototype.say = function(){
                           return 'My name is ' + this.name;
                       };

                       function Child(name){
                           Parent.apply(this, arguments);
                       };

                       function inherit(C, P){
                           C.prototype = new P();
                       };
                       inherit(Child, Parent);
                       var dad = new Parent('Larry');
                       var kid = new Child('Scott');
                       console.log(dad.say()); // 'My name is Larry'
                       console.log(kid.say()); // 'My name is Scott'

Wednesday, November 10, 2010
Drawback: parent constructor is called twice
                       function Parent(name){
                           this.name = name;
                       };
                       Parent.prototype.say = function(){
                           return 'My name is ' + this.name;
                       };

                       function Child(name){
                           Parent.apply(this, arguments);
                       };

                       function inherit(C, P){
                           C.prototype = new P();
                       };
                       inherit(Child, Parent);
                       var dad = new Parent('Larry');
                       var kid = new Child('Scott');
                       console.log(dad.say()); // 'My name is Larry'
                       console.log(kid.say()); // 'My name is Scott'

Wednesday, November 10, 2010
mmmm let’s try with the same prototype




Wednesday, November 10, 2010
Share the same prototype




                               function inherit(C, P){
                                   C.prototype = P.prototype;
                               };




Wednesday, November 10, 2010
Parent.prototype
                                       say()




                    new Child()                      new Parent()
                    name: Scott                       name: Larry
                    __proto__                         __proto__



Wednesday, November 10, 2010
Share the same prototype




                               Inheritance works as expected
                               Constructor called only once
                               Low memory footprint




Wednesday, November 10, 2010
Share the same prototype




                               Child objects can affect other objects




Wednesday, November 10, 2010
Enhance the pattern: temporary constructor




                               function inherit(C, P) {
                                   var F = function () {};
                                   F.prototype = P.prototype;
                                   C.prototype = new F();
                               };




Wednesday, November 10, 2010
Parent.prototype
                                    say()
            new Parent()                            new F()
             name: Larry                           __proto__
             __proto__




                                         new Child()
                                         name: Scott
                                         __proto__
Wednesday, November 10, 2010
The Holy Grail Pattern of classical inheritance




                               function inherit(C, P) {
                                   var F = function () {};
                                   F.prototype = P.prototype;
                                   C.prototype = new F();
                                   C.uber = P.prototype;
                                   C.prototype.constructor = C;
                               };




Wednesday, November 10, 2010
We got it!




Wednesday, November 10, 2010
What about Prototypal Inheritance?




Wednesday, November 10, 2010
No more classes, only objects




Wednesday, November 10, 2010
What we want in prototypal inheritance



                               var parent = {
                                   name: "Larry",
                                   say: function(){
                                       return "My name is " + this.name;
                                   }
                               };

                               var child = object(parent);
                               child.name = 'Scott'

                               console.log(child.say()); // "Scott"




Wednesday, November 10, 2010
Prototypal inheritance function




                                      function object(o) {
                                          function F() {}
                                          F.prototype = o;
                                          return new F();
                                      };




Wednesday, November 10, 2010
parent
                               name: Scott
                                  say()




                                             child = new F()
                                               name: Larry
                                               __proto__



Wednesday, November 10, 2010
With constructor function


                               var Parent = function(name){
                                   this.name = name;
                                   this.say = function(){
                                       return "My name is " + this.name;
                                   }
                               };

                               var child = object(new Parent("Larry"));
                               child.name = 'Scott'

                               console.log(child.say()); // "Scott"




Wednesday, November 10, 2010
better classical or prototypal?




Wednesday, November 10, 2010
It depends




Wednesday, November 10, 2010
Goals of inheritance is reuse and reduce duplication




Wednesday, November 10, 2010
isA relationship...
                        Liskov principle...
                  difficult to tame inheritance...




Wednesday, November 10, 2010
A modern and better approach is to use


                                   Mix-In




Wednesday, November 10, 2010
A beahviour...


                               var Serializer = function () {};
                               Serializer.prototype = {
                                   serialize: function () {
                                       var output = [];
                                       for (key in this) {
                                           // append this[key] to output
                               	 	 	      // ...
                                       }
                                       return output.join(', ');
                                   }
                               };




Wednesday, November 10, 2010
another beahviour...


                       var XmlBuilder = function () {};
                       XmlBuilder.prototype = {
                           toXml: function () {
                               var output = '';
                               for (key in this) {
                                    // append xml of this[key] to output
                                    // ...
                               }
                               return output;
                           }
                       };




Wednesday, November 10, 2010
and an object...



                               var Author = function (name, books) {
                                   this.name = name || "";
                                   this.books = books || [];
                               }




Wednesday, November 10, 2010
result!
       augment(Author, Serializer);
       augment(Author, XmlBuilder);

       var author = new Author('Umberto Eco',
                               ['Il nome della rosa',
                                'Il Pendolo di Foucault']);
       var serializedString = author.serialize();
       console.log(serializedString); // name: Umberto Eco,
                                       // books: Il nome della rosa,
                                      // Il Pendolo di Foucault
       var xmlString = author.toXml();
       console.log(xmlString); //<name>Umberto Eco</name>
                               // <book>Il nome della rosa</book>
       	 	 	 	 	 	             // <book>Il Pendolo di Focault</book>




Wednesday, November 10, 2010
The recipe



                  function augment(receivingClass, givingClass) {
                      for (methodName in givingClass.prototype) {
                          if (!receivingClass.prototype[methodName]) {
                              receivingClass.prototype[methodName] =
                               givingClass.prototype[methodName];
                          }
                      }
                  }




Wednesday, November 10, 2010
Advanced
                               Design Patterns




Wednesday, November 10, 2010
Wednesday, November 10, 2010
“A design pattern is a
                               general reusable solution to
                               a commonly occurring
                               problem”




Wednesday, November 10, 2010
JavaScript is not J@#*!




Wednesday, November 10, 2010
Factory pattern
                  creation of objects
                  subclasses decide which class to instantiate




Wednesday, November 10, 2010
var BicycleFactory = {
      createBicycle: function(model){
          var bicycle;
          switch (model) {
              case 'The Speedster':
                  bicycle = new Speedster();
                  break;
              case 'The Lowrider':
                  bicycle = new Lowrider();
                  break;
              case 'The Comfort Cruiser':
              default:
                  bicycle = new ComfortCruiser();
          }
          Interface.ensureImplements(bicycle, Bicycle);
          bicycle.assemble();
          bicycle.wash();
          return bicycle;
      }
  };
  var californiaCruisers = new BicycleFactory();
  var yourNewBike = californiaCruisers.createBicycle('The Speedster');

Wednesday, November 10, 2010
A more concrete example...

     var XMLHttpFactory = function(){
         this.createXMLHttp = function(){
             if (typeof XMLHttpRequest !== "undefined") {
                  return XMLHttpRequest();
             }
             else
                  if (typeof window.ActiveXObject !== "undefined") {
                      return ActiveXObject("MSXML2.XMLHttp");
                  }
                  else {
                      alert("XHR Object not in production");
                  }
         }
     };

     var xhr = new XMLHttpFactory().createXMLHttp();




Wednesday, November 10, 2010
It seems lightly broken....




Wednesday, November 10, 2010
var XMLHttpFactory = function(){
         this.createXMLHttp = function(){
             if (typeof XMLHttpRequest !== "undefined") {
                  return XMLHttpRequest();
             }
             else
                  if (typeof window.ActiveXObject !== "undefined") {
                      return ActiveXObject("MSXML2.XMLHttp");
                  }
                  else {
                      alert("XHR Object not in production");
                  }
         }
     };

     var xhr = new XMLHttpFactory().createXMLHttp();




Wednesday, November 10, 2010
Chain of Responsibility pattern




Wednesday, November 10, 2010
Extract condition and action....



                       var XhrStandard = function(){
                            this.canHandle = function(){
                              return typeof XMLHttpRequest !== "undefined";
                            }

                               this.xhr = function(){
                                 return XMLHttpRequest();
                               }
                         };




Wednesday, November 10, 2010
another condition and action....




                         var XhrIe = function(){
                             this.canHandle = function(){
                               return typeof ActiveXObject !== "undefined";
                             }
                            this.xhr = function(){
                               return ActiveXObject("MSXML2.XMLHttp");
                             }
                         };




Wednesday, November 10, 2010
and last one condition and action....




                               var XhrError = function(){
                                   this.canHandle = function(){
                                     return true;
                                   }
                                  this.xhr = function(){
                                     throw("XHR Object not in production");
                                   }
                               };




Wednesday, November 10, 2010
and the engine!
                var XMLHttpFactory = function(){
                    //... ChainLinks...
                    var creators = [new XhrStandard(),
                                    new XhrIe(),
                                    new XhrError()];

                         this.createXMLHttp = function(){
                                 var creator;
                                 for(var i = 0; i < creators.length; ++i){
                                     creator = creators[i];
                                     if(creator.canHandle()) {
                                         return creator.xhr();
                                     }
                                 }
                         }
                };

                var xhr = new XMLHttpFactory().createXMLHttp();
                console.log(xhr);



Wednesday, November 10, 2010
Or following the book...




Wednesday, November 10, 2010
Refactored an action...
                   var XhrStandard = function(){
                       this.canHandle = function(){
                           return typeof XMLHttpRequest !== "undefined";
                       }

                               this.xhr = function(){
                                   if (this.canHandle()) {
                                       return XMLHttpRequest();
                                   }
                                   return this.successor.xhr();
                               }

                               this.addSuccessor = function(successor){
                                   this.successor = successor;
                                   return this.successor;
                               }
                   };




Wednesday, November 10, 2010
other action...
                      var XhrIe = function(){
                          this.canHandle = function(){
                              return typeof ActiveXObject !== "undefined";
                          }
                          this.xhr = function(){
                              if (this.canHandle()) {
                                  return ActiveXObject("MSXML2.XMLHttp");
                              }
                              return this.successor.xhr();
                          }

                               this.addSuccessor = function(successor){
                                   this.successor = successor;
                                   return this.successor;
                               }
                      };




Wednesday, November 10, 2010
last action...


                         var XhrError = function(){
                             this.canHandle = function(){
                                 return true;
                             }
                             this.xhr = function(){
                                 throw ("XHR Object not in production");
                             }
                             this.addSuccessor = function(successor){
                                 this.successor = successor;
                                 return this.successor;
                             }
                         };




Wednesday, November 10, 2010
and the engine!
                   var XMLHttpFactory = function(){
                     //... ChainLinks...

                               var creator = (function(){
                                   var head = new XhrIe();
                                   head.addSuccessor(new XhrStandard())
                                       .addSuccessor(new XhrError());
                                   return head;
                               })();

                               this.createXMLHttp = function(){
                                   return creator.xhr();
                               }
                   };

                   var xhr = new XMLHttpFactory().createXMLHttp();
                   console.log(xhr);




Wednesday, November 10, 2010
mmm duplication...




Wednesday, November 10, 2010
Same for all...
                      var XhrIe = function(){
                          this.canHandle = function(){
                              return typeof ActiveXObject !== "undefined";
                          }
                          this.xhr = function(){
                              if (this.canHandle()) {
                                  return ActiveXObject("MSXML2.XMLHttp");
                              }
                              return this.successor.xhr();
                          }

                               this.addSuccessor = function(successor){
                                   this.successor = successor;
                                   return this.successor;
                               }
                      };




Wednesday, November 10, 2010
Similar for all..
                      var XhrIe = function(){
                          this.canHandle = function(){
                              return typeof ActiveXObject !== "undefined";
                          }
                          this.xhr = function(){
                              if (this.canHandle()) {
                                  return ActiveXObject("MSXML2.XMLHttp");
                              }
                              return this.successor.xhr();
                          }

                               this.addSuccessor = function(successor){
                                   this.successor = successor;
                                   return this.successor;
                               }
                      };




Wednesday, November 10, 2010
Template Method pattern




Wednesday, November 10, 2010
Template Method pattern



                               ... and a little bit of Mix-In




Wednesday, November 10, 2010
Extracted same and similar behaviours....


                var ChainLink = function() {};
                ChainLink.prototype.exec = function(){
                       if(this.canHandle()) {
                         return this.doIt();
                       }
                       return this.successor.exec();
                    };

                         ChainLink.prototype.addSuccessor = function(successor){
                             this.successor = successor;
                             return this.successor;
                         }




Wednesday, November 10, 2010
Augment an action...



                       var XhrStandard = augment(function(){
                           this.canHandle = function(){
                              return typeof XMLHttpRequest !== "undefined";
                           }
                           this.doIt = function(){
                                  return XMLHttpRequest();
                           };
                       }, ChainLink);




Wednesday, November 10, 2010
another action...




                 var XhrIe = augment(function(){
                     this.canHandle = function(){
                        return typeof ActiveXObject !== "undefined";
                     }
                     this.doIt = function(){
                          return this.doIt();
                     };
                 }, ChainLink);




Wednesday, November 10, 2010
and last one.



                               var XhrError = augment(function(){
                                   this.canHandle = function(){
                                     return true;
                                   }

                                   this.doIt = function(){
                                     throw("XHR Object not in production");
                                   }
                               },ChainLink);




Wednesday, November 10, 2010
and the engine is the same!
                   var XMLHttpFactory = function(){
                     //... ChainLinks...

                               var creator = (function(){
                                   var head = new XhrIe();
                                   head.addSuccessor(new XhrStandard())
                                       .addSuccessor(new XhrError());
                                   return head;
                               })();

                               this.createXMLHttp = function(){
                                   return creator.xhr();
                               }
                   };

                   var xhr = new XMLHttpFactory().createXMLHttp();
                   console.log(xhr);




Wednesday, November 10, 2010
It’s just a beginning...




Wednesday, November 10, 2010
peep code


Wednesday, November 10, 2010
Study




Wednesday, November 10, 2010
Wednesday, November 10, 2010
Wednesday, November 10, 2010
“Save it for a rainy day!”




Wednesday, November 10, 2010
Check your code with jslint.com




Wednesday, November 10, 2010
Wednesday, November 10, 2010
giordano.scalzo@cleancode.it
                               @giordanoscalzo
                               www.slideshare.net/giordano
                               github.com/gscalzo
Wednesday, November 10, 2010

More Related Content

What's hot (19)

TypoScript 2.0
TypoScript 2.0
Robert Lemke
 
Basic Mechanism of OOPL
Basic Mechanism of OOPL
kwatch
 
Java synchronizers
Java synchronizers
ts_v_murthy
 
Prototype
Prototype
Aditya Gaur
 
Js in the open
Js in the open
Victor Porof
 
Tech Talks - Fundamentos JavaScript
Tech Talks - Fundamentos JavaScript
BVision
 
Floggy-M3DD-2009-01-21
Floggy-M3DD-2009-01-21
Thiago Leão Moreira
 
The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196
Mahmoud Samir Fayed
 
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
CodeFest
 
不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして
mitsutaka mimura
 
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
Guillaume Laforge
 
Threads
Threads
Then Murugeshwari
 
Objective-C for Beginners
Objective-C for Beginners
Adam Musial-Bright
 
Java Concurrency Gotchas
Java Concurrency Gotchas
Alex Miller
 
Swift 3 Programming for iOS : subscript init
Swift 3 Programming for iOS : subscript init
Kwang Woo NAM
 
Python for text processing
Python for text processing
Xiang Li
 
Python introduction
Python introduction
Marcelo Araujo
 
Cleanup and new optimizations in WPython 1.1
Cleanup and new optimizations in WPython 1.1
PyCon Italia
 
PyFoursquare: Python Library for Foursquare
PyFoursquare: Python Library for Foursquare
Marcel Caraciolo
 
Basic Mechanism of OOPL
Basic Mechanism of OOPL
kwatch
 
Java synchronizers
Java synchronizers
ts_v_murthy
 
Tech Talks - Fundamentos JavaScript
Tech Talks - Fundamentos JavaScript
BVision
 
The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196
Mahmoud Samir Fayed
 
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
CodeFest
 
不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして
mitsutaka mimura
 
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
Guillaume Laforge
 
Java Concurrency Gotchas
Java Concurrency Gotchas
Alex Miller
 
Swift 3 Programming for iOS : subscript init
Swift 3 Programming for iOS : subscript init
Kwang Woo NAM
 
Python for text processing
Python for text processing
Xiang Li
 
Cleanup and new optimizations in WPython 1.1
Cleanup and new optimizations in WPython 1.1
PyCon Italia
 
PyFoursquare: Python Library for Foursquare
PyFoursquare: Python Library for Foursquare
Marcel Caraciolo
 

Viewers also liked (7)

Loosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain model
Francesca1980
 
"Don't call us, we'll call you" - AngularJS meets Event-Driven Architecture
"Don't call us, we'll call you" - AngularJS meets Event-Driven Architecture
Luca Milan
 
[Alam aeki] Guida illustrata alla modellazione di un dominio con Event Sourci...
[Alam aeki] Guida illustrata alla modellazione di un dominio con Event Sourci...
Andrea Balducci
 
Layered Expression Trees feat. CQRS
Layered Expression Trees feat. CQRS
Andrea Saltarello
 
SUE AGILE Architettura (Italiano)
SUE AGILE Architettura (Italiano)
Sabino Labarile
 
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventi
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventi
Gabriele Marazzi
 
Architetttura Della Soluzione
Architetttura Della Soluzione
Luca Milan
 
Loosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain model
Francesca1980
 
"Don't call us, we'll call you" - AngularJS meets Event-Driven Architecture
"Don't call us, we'll call you" - AngularJS meets Event-Driven Architecture
Luca Milan
 
[Alam aeki] Guida illustrata alla modellazione di un dominio con Event Sourci...
[Alam aeki] Guida illustrata alla modellazione di un dominio con Event Sourci...
Andrea Balducci
 
Layered Expression Trees feat. CQRS
Layered Expression Trees feat. CQRS
Andrea Saltarello
 
SUE AGILE Architettura (Italiano)
SUE AGILE Architettura (Italiano)
Sabino Labarile
 
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventi
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventi
Gabriele Marazzi
 
Architetttura Della Soluzione
Architetttura Della Soluzione
Luca Milan
 
Ad

Similar to Java scriptpatterns (20)

JavaScript: Advanced Scoping & Other Puzzles
JavaScript: Advanced Scoping & Other Puzzles
Sencha
 
Javascript Basics - part 1
Javascript Basics - part 1
Kasia Drzyzga
 
03 Advanced JavaScript
03 Advanced JavaScript
Ynon Perek
 
JSLent: give it up for JavaScript
JSLent: give it up for JavaScript
BigBlueHat
 
Wakanday JS201 Best Practices
Wakanday JS201 Best Practices
Juergen Fesslmeier
 
Java Script Patterns
Java Script Patterns
Allan Huang
 
Javascript the Interlingua of the Web
Javascript the Interlingua of the Web
andersjanmyr
 
Javascript classes and scoping
Javascript classes and scoping
Patrick Sheridan
 
Awesomeness of JavaScript…almost
Awesomeness of JavaScript…almost
Quinton Sheppard
 
Understanding JavaScript
Understanding JavaScript
nodejsbcn
 
Wintellect - Devscovery - Enterprise JavaScript Development 1 of 2
Wintellect - Devscovery - Enterprise JavaScript Development 1 of 2
Jeremy Likness
 
JavaScript Primer
JavaScript Primer
Daniel Cousineau
 
Introduction to Client-Side Javascript
Introduction to Client-Side Javascript
Julie Iskander
 
Design patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjs
Ravi Bhadauria
 
Goodparts
Goodparts
damonjablons
 
Future-proofing Your JavaScript Apps (Compact edition)
Future-proofing Your JavaScript Apps (Compact edition)
Addy Osmani
 
Enterprise javascriptsession1
Enterprise javascriptsession1
Troy Miles
 
Javascript fundamentals and not
Javascript fundamentals and not
Salvatore Fazio
 
JavaScript - Like a Box of Chocolates
JavaScript - Like a Box of Chocolates
Robert Nyman
 
Responsible JavaScript
Responsible JavaScript
Michael Girouard
 
JavaScript: Advanced Scoping & Other Puzzles
JavaScript: Advanced Scoping & Other Puzzles
Sencha
 
Javascript Basics - part 1
Javascript Basics - part 1
Kasia Drzyzga
 
03 Advanced JavaScript
03 Advanced JavaScript
Ynon Perek
 
JSLent: give it up for JavaScript
JSLent: give it up for JavaScript
BigBlueHat
 
Java Script Patterns
Java Script Patterns
Allan Huang
 
Javascript the Interlingua of the Web
Javascript the Interlingua of the Web
andersjanmyr
 
Javascript classes and scoping
Javascript classes and scoping
Patrick Sheridan
 
Awesomeness of JavaScript…almost
Awesomeness of JavaScript…almost
Quinton Sheppard
 
Understanding JavaScript
Understanding JavaScript
nodejsbcn
 
Wintellect - Devscovery - Enterprise JavaScript Development 1 of 2
Wintellect - Devscovery - Enterprise JavaScript Development 1 of 2
Jeremy Likness
 
Introduction to Client-Side Javascript
Introduction to Client-Side Javascript
Julie Iskander
 
Design patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjs
Ravi Bhadauria
 
Future-proofing Your JavaScript Apps (Compact edition)
Future-proofing Your JavaScript Apps (Compact edition)
Addy Osmani
 
Enterprise javascriptsession1
Enterprise javascriptsession1
Troy Miles
 
Javascript fundamentals and not
Javascript fundamentals and not
Salvatore Fazio
 
JavaScript - Like a Box of Chocolates
JavaScript - Like a Box of Chocolates
Robert Nyman
 
Ad

More from Francesca1980 (9)

Map meshup
Map meshup
Francesca1980
 
Java scriptpatterns
Java scriptpatterns
Francesca1980
 
Event driven javascript
Event driven javascript
Francesca1980
 
Event driven javascript
Event driven javascript
Francesca1980
 
Simple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computing
Francesca1980
 
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
Francesca1980
 
Writing cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI Bindings
Francesca1980
 
Programmazione web libera dai framework
Programmazione web libera dai framework
Francesca1980
 
Event driven javascript
Event driven javascript
Francesca1980
 
Event driven javascript
Event driven javascript
Francesca1980
 
Simple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computing
Francesca1980
 
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
Francesca1980
 
Writing cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI Bindings
Francesca1980
 
Programmazione web libera dai framework
Programmazione web libera dai framework
Francesca1980
 

Java scriptpatterns

  • 1. JavaScript Patterns Giordano Scalzo Wednesday, November 10, 2010
  • 2. I’m not a guru! Wednesday, November 10, 2010
  • 5. JavaScript isn’t this anymore Wednesday, November 10, 2010
  • 7. JavaScript is trendy! Technology Radar Wednesday, November 10, 2010
  • 8. JavaScript is trendy! Technology Radar Wednesday, November 10, 2010
  • 9. At the beginning... Wednesday, November 10, 2010
  • 10. Hacked by Brendan Eich in one week... Wednesday, November 10, 2010
  • 11. Former Mocha, renamed to JavaScript by Netscape Wednesday, November 10, 2010
  • 12. after a while... Wednesday, November 10, 2010
  • 16. Back to study! Wednesday, November 10, 2010
  • 17. Started a notebook... Wednesday, November 10, 2010
  • 18. Essential Scope Wednesday, November 10, 2010
  • 19. function sum(x, y){ // implied global result = x + y; return result; } {antipattern} Wednesday, November 10, 2010
  • 20. Global variables are evil! Wednesday, November 10, 2010
  • 22. Always declare variables with var function sum(x, y){ var result = x + y; return result; } {pattern} Wednesday, November 10, 2010
  • 23. function foo(){ var a = b = 0; //... } {antipattern} Wednesday, November 10, 2010
  • 24. b become global function foo(){ var a = (b = 0); //... } {antipattern} Wednesday, November 10, 2010
  • 25. don’t use assign chain in definition function foo(){ var a, b; a = b = 0; //... } {pattern} Wednesday, November 10, 2010
  • 26. Single var pattern function func(){ var a = 1, b = 2, sum = a + b, myobject = {}, i, j; // function body... } {pattern} Wednesday, November 10, 2010
  • 27. Don’t forget comma otherwise... Wednesday, November 10, 2010
  • 28. ... variables become globals Wednesday, November 10, 2010
  • 29. Hoisting myname = "global"; // global variable function func(){ // code... console.log(myname); // "undefined" // code... var myname = "local"; console.log(myname); // "local" } func(); {antipattern} Wednesday, November 10, 2010
  • 30. Hoisting myname = "global"; // global variable function func(){ var myname = "declared"; // code... console.log(myname); // "declared" // code... myname = "local"; console.log(myname); // "local" } func(); {pattern} Wednesday, November 10, 2010
  • 31. Against minimum vertical distance principle “Variables should be declared as close to their usage as possible” Robert C. Martin - Clean Code Wednesday, November 10, 2010
  • 32. Essential Literal and Constructor Wednesday, November 10, 2010
  • 33. In JavaScript almost everything is an object Wednesday, November 10, 2010
  • 34. It’s easy... var person = new Object(); person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); Wednesday, November 10, 2010
  • 35. but wrong! :-( var person = new Object(); person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); {antipattern} Wednesday, November 10, 2010
  • 36. var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); {pattern} Wednesday, November 10, 2010
  • 37. What if we need similar objects... var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); // I am Scott var otherPerson = {}; otherPerson.name = "Tiger"; otherPerson.say = function(){ return "I am " + this.name; }; console.log(otherPerson.say()); // I am Tiger Wednesday, November 10, 2010
  • 38. A lot of duplication var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); // I am Scott var otherPerson = {}; otherPerson.name = "Tiger"; otherPerson.say = function(){ return "I am " + this.name; }; console.log(otherPerson.say()); // I am Tiger Wednesday, November 10, 2010
  • 39. Duplication is evil! Wednesday, November 10, 2010
  • 40. Custom Constructor Functions var Person = function(name){ this.name = name; this.say = function(){ return "I am " + this.name; } } var person = new Person("Scott"); console.log(person.say()); // I am Scott {pattern} Wednesday, November 10, 2010
  • 41. Behind the scenes... var Person = function(name){ // var this = {}; this.name = name; this.say = function(){ return "I am " + this.name; }; // return this; }; {pattern} Wednesday, November 10, 2010
  • 42. So, at the end... var Person = function(name){ this.name = name; this.say = function(){ return "I am " + this.name; }; }; var scott = new Person('Scott'); var tiger = new Person('Tiger'); console.log(scott.say()); console.log(tiger.say()); {pattern} Wednesday, November 10, 2010
  • 43. What if we forget new? Wednesday, November 10, 2010
  • 44. this will point to global object var Person = function(name){ this.name = name; this.say = function(){ return "I am " + this.name; }; }; var scott = new Person('Scott') var adam = Person('Adam') console.log(typeof scott); //object console.log(scott.name); // Scott console.log(typeof adam); //'undefined' console.log(window.name); // Adam Wednesday, November 10, 2010
  • 45. Enforce new pattern one: naming convention Wednesday, November 10, 2010
  • 46. var Person = function(name){ var that = {}; that.name = name; that.say = function(){ return "I am " + that.name;}; return that; }; var scott = new Person('Scott') var adam = Person('Adam') console.log(typeof scott); //Object console.log(scott.name); // Scott console.log(typeof adam); //Object console.log(adam.name); // Adam {pattern} Wednesday, November 10, 2010
  • 47. Drawback: we loose prototype reference :-( var Person = function(name){ var that = {}; that.name = name; that.say = function(){ return "I am " + that.name; }; return that; }; Person.prototype.iamhumanbeing = true; var scott = new Person('Scott') var adam = Person('Adam') console.log(scott.iamhumanbeing); // undefined console.log(adam.iamhumanbeing); // undefined Wednesday, November 10, 2010
  • 48. Interm!zo Prototype property Wednesday, November 10, 2010
  • 49. Define ancestors chain var foo = {one: 1, two: 2}; var bar = {three: 3}; foo.__proto__ = bar; console.log(foo.one); console.log(foo.three); Wednesday, November 10, 2010
  • 50. bar three: 3 foo one: 1 two: 2 __proto__ Wednesday, November 10, 2010
  • 51. Behind the scenes... var Person = function(name){ // this.prototype = {constructor: this} var that = {}; that.name = name; that.say = function(){ return "I am " + that.name; }; return that; }; Wednesday, November 10, 2010
  • 52. Self invoking constructor var Person = function(name){ if (this instanceof Person) { this.name = name; this.say = function(){ return "I am " + that.name; } } else { return new Person(name); } }; Person.prototype.iamhumanbeing = true; var scott = new Person('Scott') var adam = Person('Adam') console.log(scott.name); // Scott console.log(adam.name); // Adam console.log(scott.iamhumanbeing); // true console.log(adam.iamhumanbeing); // true {pattern} Wednesday, November 10, 2010
  • 53. Essential Functions Wednesday, November 10, 2010
  • 54. Functions as first class objects Wednesday, November 10, 2010
  • 55. Immediate functions (function(){ alert('watch out!'); })(); Wednesday, November 10, 2010
  • 56. Initialization pattern (function(){ var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], today = new Date(), msg = 'Today is ' + days[today.getDay()] + ', ' + today.getDate(); console.log(msg); })(); // "Today is Wed, 10" {pattern} Wednesday, November 10, 2010
  • 58. 5 globals... // constructors function Parent(){ } function Child(){ } // a variable var some_var = 1; // some objects var module1 = {}; module1.data = { a: 1, b: 2 }; var module2 = {}; {antipattern} Wednesday, November 10, 2010
  • 59. 1 global! // global object var MYAPP = (function(){ var my = {}; {pattern} // constructors my.Parent = function(){}; my.Child = function(){}; // a variable my.some_var = 1; // an object container my.modules = {}; // nested objects my.modules.module1 = {}; my.modules.module1.data = { a: 1, b: 2 }; my.modules.module2 = {}; return my; })(); console.log(MYAPP.modules.module1.data.a); // 1 Wednesday, November 10, 2010
  • 61. function Gadget(){ this.name = 'iPod'; this.stretch = function(){ return 'iPad'; } }; var toy = new Gadget(); console.log(toy.name); // `iPod` toy.name = 'Zune' console.log(toy.name); // `Zune` is public console.log(toy.stretch()); // stretch() is public {antipattern} Wednesday, November 10, 2010
  • 62. Create private member function Gadget(){ var name = 'iPod'; this.getName = function(){ return name; } }; var toy = new Gadget(); console.log(toy.getName()); // `iPod` toy.name = 'Zune' console.log(toy.getName()); // `iPod` {pattern} Wednesday, November 10, 2010
  • 63. for methods too function Gadget() { var name = 'iPod'; var upgrade = function(){ return 'iPhone'; } this.getName = function () { return name; } this.pay = function() { return upgrade(); } }; var toy = new Gadget(); console.log(toy.pay()); // `iPhone` console.log(toy.upgrade()); // `error` {pattern} Wednesday, November 10, 2010
  • 64. Advanced Code reuse patterns Wednesday, November 10, 2010
  • 65. Classical vs prototypal inheritance vs Wednesday, November 10, 2010
  • 66. Classical inheritance function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ this.name = name; }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 67. function(){ return 'My name is ' + this.name; }; Parent.prototype say() new Parent() name: Larry __proto__ console.log(dad.say()); Wednesday, November 10, 2010
  • 68. Default Classical Inheritance pattern function inherit(C, P) { C.prototype = new P(); }; Wednesday, November 10, 2010
  • 69. function(){ return 'My name is ' + this.name; }; Parent.prototype say() new Parent() new Child() name: Larry name: Scott __proto__ __proto__ console.log(kid.say()); Wednesday, November 10, 2010
  • 70. Drawback: it doesn’t call parent constructor function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ this.name = name; }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 71. Drawback: it doesn’t call parent constructor function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ }; function inherit(C, P) { C.prototype = new P(); }; inherit(Child, Parent); var kid = new Child('Scott'); console.log(kid.say()); // 'My name is undefined' Wednesday, November 10, 2010
  • 72. Pattern Extension: rent a constructor function Child(name){ Parent.apply(this, arguments); }; Wednesday, November 10, 2010
  • 73. Pattern Extension: rent a constructor function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 74. Drawback: parent constructor is called twice function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 75. Drawback: parent constructor is called twice function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 76. Drawback: parent constructor is called twice function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return 'My name is ' + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent('Larry'); var kid = new Child('Scott'); console.log(dad.say()); // 'My name is Larry' console.log(kid.say()); // 'My name is Scott' Wednesday, November 10, 2010
  • 77. mmmm let’s try with the same prototype Wednesday, November 10, 2010
  • 78. Share the same prototype function inherit(C, P){ C.prototype = P.prototype; }; Wednesday, November 10, 2010
  • 79. Parent.prototype say() new Child() new Parent() name: Scott name: Larry __proto__ __proto__ Wednesday, November 10, 2010
  • 80. Share the same prototype Inheritance works as expected Constructor called only once Low memory footprint Wednesday, November 10, 2010
  • 81. Share the same prototype Child objects can affect other objects Wednesday, November 10, 2010
  • 82. Enhance the pattern: temporary constructor function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); }; Wednesday, November 10, 2010
  • 83. Parent.prototype say() new Parent() new F() name: Larry __proto__ __proto__ new Child() name: Scott __proto__ Wednesday, November 10, 2010
  • 84. The Holy Grail Pattern of classical inheritance function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; C.prototype.constructor = C; }; Wednesday, November 10, 2010
  • 85. We got it! Wednesday, November 10, 2010
  • 86. What about Prototypal Inheritance? Wednesday, November 10, 2010
  • 87. No more classes, only objects Wednesday, November 10, 2010
  • 88. What we want in prototypal inheritance var parent = { name: "Larry", say: function(){ return "My name is " + this.name; } }; var child = object(parent); child.name = 'Scott' console.log(child.say()); // "Scott" Wednesday, November 10, 2010
  • 89. Prototypal inheritance function function object(o) { function F() {} F.prototype = o; return new F(); }; Wednesday, November 10, 2010
  • 90. parent name: Scott say() child = new F() name: Larry __proto__ Wednesday, November 10, 2010
  • 91. With constructor function var Parent = function(name){ this.name = name; this.say = function(){ return "My name is " + this.name; } }; var child = object(new Parent("Larry")); child.name = 'Scott' console.log(child.say()); // "Scott" Wednesday, November 10, 2010
  • 92. better classical or prototypal? Wednesday, November 10, 2010
  • 94. Goals of inheritance is reuse and reduce duplication Wednesday, November 10, 2010
  • 95. isA relationship... Liskov principle... difficult to tame inheritance... Wednesday, November 10, 2010
  • 96. A modern and better approach is to use Mix-In Wednesday, November 10, 2010
  • 97. A beahviour... var Serializer = function () {}; Serializer.prototype = { serialize: function () { var output = []; for (key in this) { // append this[key] to output // ... } return output.join(', '); } }; Wednesday, November 10, 2010
  • 98. another beahviour... var XmlBuilder = function () {}; XmlBuilder.prototype = { toXml: function () { var output = ''; for (key in this) { // append xml of this[key] to output // ... } return output; } }; Wednesday, November 10, 2010
  • 99. and an object... var Author = function (name, books) { this.name = name || ""; this.books = books || []; } Wednesday, November 10, 2010
  • 100. result! augment(Author, Serializer); augment(Author, XmlBuilder); var author = new Author('Umberto Eco', ['Il nome della rosa', 'Il Pendolo di Foucault']); var serializedString = author.serialize(); console.log(serializedString); // name: Umberto Eco, // books: Il nome della rosa, // Il Pendolo di Foucault var xmlString = author.toXml(); console.log(xmlString); //<name>Umberto Eco</name> // <book>Il nome della rosa</book> // <book>Il Pendolo di Focault</book> Wednesday, November 10, 2010
  • 101. The recipe function augment(receivingClass, givingClass) { for (methodName in givingClass.prototype) { if (!receivingClass.prototype[methodName]) { receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } } } Wednesday, November 10, 2010
  • 102. Advanced Design Patterns Wednesday, November 10, 2010
  • 104. “A design pattern is a general reusable solution to a commonly occurring problem” Wednesday, November 10, 2010
  • 105. JavaScript is not J@#*! Wednesday, November 10, 2010
  • 106. Factory pattern creation of objects subclasses decide which class to instantiate Wednesday, November 10, 2010
  • 107. var BicycleFactory = { createBicycle: function(model){ var bicycle; switch (model) { case 'The Speedster': bicycle = new Speedster(); break; case 'The Lowrider': bicycle = new Lowrider(); break; case 'The Comfort Cruiser': default: bicycle = new ComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); bicycle.assemble(); bicycle.wash(); return bicycle; } }; var californiaCruisers = new BicycleFactory(); var yourNewBike = californiaCruisers.createBicycle('The Speedster'); Wednesday, November 10, 2010
  • 108. A more concrete example... var XMLHttpFactory = function(){ this.createXMLHttp = function(){ if (typeof XMLHttpRequest !== "undefined") { return XMLHttpRequest(); } else if (typeof window.ActiveXObject !== "undefined") { return ActiveXObject("MSXML2.XMLHttp"); } else { alert("XHR Object not in production"); } } }; var xhr = new XMLHttpFactory().createXMLHttp(); Wednesday, November 10, 2010
  • 109. It seems lightly broken.... Wednesday, November 10, 2010
  • 110. var XMLHttpFactory = function(){ this.createXMLHttp = function(){ if (typeof XMLHttpRequest !== "undefined") { return XMLHttpRequest(); } else if (typeof window.ActiveXObject !== "undefined") { return ActiveXObject("MSXML2.XMLHttp"); } else { alert("XHR Object not in production"); } } }; var xhr = new XMLHttpFactory().createXMLHttp(); Wednesday, November 10, 2010
  • 111. Chain of Responsibility pattern Wednesday, November 10, 2010
  • 112. Extract condition and action.... var XhrStandard = function(){ this.canHandle = function(){ return typeof XMLHttpRequest !== "undefined"; } this.xhr = function(){ return XMLHttpRequest(); } }; Wednesday, November 10, 2010
  • 113. another condition and action.... var XhrIe = function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.xhr = function(){ return ActiveXObject("MSXML2.XMLHttp"); } }; Wednesday, November 10, 2010
  • 114. and last one condition and action.... var XhrError = function(){ this.canHandle = function(){ return true; } this.xhr = function(){ throw("XHR Object not in production"); } }; Wednesday, November 10, 2010
  • 115. and the engine! var XMLHttpFactory = function(){ //... ChainLinks... var creators = [new XhrStandard(), new XhrIe(), new XhrError()]; this.createXMLHttp = function(){ var creator; for(var i = 0; i < creators.length; ++i){ creator = creators[i]; if(creator.canHandle()) { return creator.xhr(); } } } }; var xhr = new XMLHttpFactory().createXMLHttp(); console.log(xhr); Wednesday, November 10, 2010
  • 116. Or following the book... Wednesday, November 10, 2010
  • 117. Refactored an action... var XhrStandard = function(){ this.canHandle = function(){ return typeof XMLHttpRequest !== "undefined"; } this.xhr = function(){ if (this.canHandle()) { return XMLHttpRequest(); } return this.successor.xhr(); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 118. other action... var XhrIe = function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.xhr = function(){ if (this.canHandle()) { return ActiveXObject("MSXML2.XMLHttp"); } return this.successor.xhr(); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 119. last action... var XhrError = function(){ this.canHandle = function(){ return true; } this.xhr = function(){ throw ("XHR Object not in production"); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 120. and the engine! var XMLHttpFactory = function(){ //... ChainLinks... var creator = (function(){ var head = new XhrIe(); head.addSuccessor(new XhrStandard()) .addSuccessor(new XhrError()); return head; })(); this.createXMLHttp = function(){ return creator.xhr(); } }; var xhr = new XMLHttpFactory().createXMLHttp(); console.log(xhr); Wednesday, November 10, 2010
  • 122. Same for all... var XhrIe = function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.xhr = function(){ if (this.canHandle()) { return ActiveXObject("MSXML2.XMLHttp"); } return this.successor.xhr(); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 123. Similar for all.. var XhrIe = function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.xhr = function(){ if (this.canHandle()) { return ActiveXObject("MSXML2.XMLHttp"); } return this.successor.xhr(); } this.addSuccessor = function(successor){ this.successor = successor; return this.successor; } }; Wednesday, November 10, 2010
  • 125. Template Method pattern ... and a little bit of Mix-In Wednesday, November 10, 2010
  • 126. Extracted same and similar behaviours.... var ChainLink = function() {}; ChainLink.prototype.exec = function(){ if(this.canHandle()) { return this.doIt(); } return this.successor.exec(); }; ChainLink.prototype.addSuccessor = function(successor){ this.successor = successor; return this.successor; } Wednesday, November 10, 2010
  • 127. Augment an action... var XhrStandard = augment(function(){ this.canHandle = function(){ return typeof XMLHttpRequest !== "undefined"; } this.doIt = function(){ return XMLHttpRequest(); }; }, ChainLink); Wednesday, November 10, 2010
  • 128. another action... var XhrIe = augment(function(){ this.canHandle = function(){ return typeof ActiveXObject !== "undefined"; } this.doIt = function(){ return this.doIt(); }; }, ChainLink); Wednesday, November 10, 2010
  • 129. and last one. var XhrError = augment(function(){ this.canHandle = function(){ return true; } this.doIt = function(){ throw("XHR Object not in production"); } },ChainLink); Wednesday, November 10, 2010
  • 130. and the engine is the same! var XMLHttpFactory = function(){ //... ChainLinks... var creator = (function(){ var head = new XhrIe(); head.addSuccessor(new XhrStandard()) .addSuccessor(new XhrError()); return head; })(); this.createXMLHttp = function(){ return creator.xhr(); } }; var xhr = new XMLHttpFactory().createXMLHttp(); console.log(xhr); Wednesday, November 10, 2010
  • 131. It’s just a beginning... Wednesday, November 10, 2010
  • 136. “Save it for a rainy day!” Wednesday, November 10, 2010
  • 137. Check your code with jslint.com Wednesday, November 10, 2010
  • 139. [email protected] @giordanoscalzo www.slideshare.net/giordano github.com/gscalzo Wednesday, November 10, 2010