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)

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

Viewers also liked (8)

PPTX
Advanced JQuery
Francesca1980
 
PPT
Loosely Coupled Complexity - Unleash the power of your domain model
Francesca1980
 
PDF
Event driven javascript
Francesca1980
 
PPTX
Michelle Hathaway Mastery Timeline
Michelle Hathaway
 
PDF
ΑΠΟΓΡΑΦΗ
steverz
 
PPTX
Open Education Resources
Michelle Hathaway
 
ODP
Writing cool web 2.0 apps with GWT and UI Bindings
Francesca1980
 
PDF
Trabajo en equipo abierto 4hrs 23 noviembre tlc
Cinet México
 
Advanced JQuery
Francesca1980
 
Loosely Coupled Complexity - Unleash the power of your domain model
Francesca1980
 
Event driven javascript
Francesca1980
 
Michelle Hathaway Mastery Timeline
Michelle Hathaway
 
ΑΠΟΓΡΑΦΗ
steverz
 
Open Education Resources
Michelle Hathaway
 
Writing cool web 2.0 apps with GWT and UI Bindings
Francesca1980
 
Trabajo en equipo abierto 4hrs 23 noviembre tlc
Cinet México
 
Ad

Similar to Java scriptpatterns (18)

PDF
µServices
Peter Kriens
 
PDF
Websockets, Ruby y Pusher Webprendedor 2010
Ismael Celis
 
PDF
The Not Java That's Not Scala
Justin Lee
 
PDF
Macruby - RubyConf Presentation 2010
Matt Aimonetti
 
PDF
MongoDB on Rails (and Ruby)
jan_mindmatters
 
PDF
D-Talk: What's awesome about Ruby 2.x and Rails 4
Jan Berdajs
 
PDF
Advanced android
donnfelker
 
PDF
Javascript the Interlingua of the Web
andersjanmyr
 
PDF
The jQuery Divide
Rebecca Murphey
 
PDF
Cleaner, Leaner, Meaner: Refactoring your jQuery
Rebecca Murphey
 
PDF
The Mobile Web @ 2010 JSConf
dion
 
PDF
Functionality Focused Code Organization
Rebecca Murphey
 
PDF
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
Andrey Breslav
 
PDF
Objective-C for Java Developers
Bob McCune
 
PDF
Meet Couch DB
estialvarez
 
PDF
Opening up the Social Web - Standards that are bridging the Islands
Bastian Hofmann
 
PDF
Using Templates to Achieve Awesomer Architecture
Garann Means
 
PDF
ZOMG WHY IS THIS CODE SO SLOW
Aaron Patterson
 
µServices
Peter Kriens
 
Websockets, Ruby y Pusher Webprendedor 2010
Ismael Celis
 
The Not Java That's Not Scala
Justin Lee
 
Macruby - RubyConf Presentation 2010
Matt Aimonetti
 
MongoDB on Rails (and Ruby)
jan_mindmatters
 
D-Talk: What's awesome about Ruby 2.x and Rails 4
Jan Berdajs
 
Advanced android
donnfelker
 
Javascript the Interlingua of the Web
andersjanmyr
 
The jQuery Divide
Rebecca Murphey
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Rebecca Murphey
 
The Mobile Web @ 2010 JSConf
dion
 
Functionality Focused Code Organization
Rebecca Murphey
 
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
Andrey Breslav
 
Objective-C for Java Developers
Bob McCune
 
Meet Couch DB
estialvarez
 
Opening up the Social Web - Standards that are bridging the Islands
Bastian Hofmann
 
Using Templates to Achieve Awesomer Architecture
Garann Means
 
ZOMG WHY IS THIS CODE SO SLOW
Aaron Patterson
 
Ad

More from Francesca1980 (6)

PPT
Map meshup
Francesca1980
 
PDF
Java scriptpatterns
Francesca1980
 
PDF
Event driven javascript
Francesca1980
 
PDF
Simple Cloud API: accesso semplificato al cloud computing
Francesca1980
 
PPTX
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
Francesca1980
 
PDF
Programmazione web libera dai framework
Francesca1980
 
Map meshup
Francesca1980
 
Java scriptpatterns
Francesca1980
 
Event driven javascript
Francesca1980
 
Simple Cloud API: accesso semplificato al cloud computing
Francesca1980
 
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
Francesca1980
 
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