SlideShare uma empresa Scribd logo
1 de 139
Baixar para ler offline
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

Mais conteúdo relacionado

Mais procurados

Basic Mechanism of OOPL
Basic Mechanism of OOPLBasic Mechanism of OOPL
Basic Mechanism of OOPLkwatch
 
Java synchronizers
Java synchronizersJava synchronizers
Java synchronizersts_v_murthy
 
Tech Talks - Fundamentos JavaScript
Tech Talks - Fundamentos JavaScriptTech Talks - Fundamentos JavaScript
Tech Talks - Fundamentos JavaScriptBVision
 
The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196Mahmoud Samir Fayed
 
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM LanguageCodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM LanguageCodeFest
 
不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして不自然な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 LaforgeGroovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume LaforgeGuillaume Laforge
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency GotchasAlex Miller
 
Swift 3 Programming for iOS : subscript init
Swift 3 Programming for iOS : subscript initSwift 3 Programming for iOS : subscript init
Swift 3 Programming for iOS : subscript initKwang Woo NAM
 
Python for text processing
Python for text processingPython for text processing
Python for text processingXiang Li
 
Cleanup and new optimizations in WPython 1.1
Cleanup and new optimizations in WPython 1.1Cleanup and new optimizations in WPython 1.1
Cleanup and new optimizations in WPython 1.1PyCon Italia
 
PyFoursquare: Python Library for Foursquare
PyFoursquare: Python Library for FoursquarePyFoursquare: Python Library for Foursquare
PyFoursquare: Python Library for FoursquareMarcel Caraciolo
 

Mais procurados (19)

TypoScript 2.0
TypoScript 2.0TypoScript 2.0
TypoScript 2.0
 
Basic Mechanism of OOPL
Basic Mechanism of OOPLBasic Mechanism of OOPL
Basic Mechanism of OOPL
 
Java synchronizers
Java synchronizersJava synchronizers
Java synchronizers
 
Prototype
PrototypePrototype
Prototype
 
Js in the open
Js in the openJs in the open
Js in the open
 
Tech Talks - Fundamentos JavaScript
Tech Talks - Fundamentos JavaScriptTech Talks - Fundamentos JavaScript
Tech Talks - Fundamentos JavaScript
 
Floggy-M3DD-2009-01-21
Floggy-M3DD-2009-01-21Floggy-M3DD-2009-01-21
Floggy-M3DD-2009-01-21
 
The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196
 
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM LanguageCodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
CodeFest 2010. Иноземцев И. — Fantom. Cross-VM Language
 
不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして不自然なcar/ナチュラルにconsして
不自然なcar/ナチュラルにconsして
 
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume LaforgeGroovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
Groovy to infinity and beyond - GR8Conf Europe 2010 - Guillaume Laforge
 
Threads
ThreadsThreads
Threads
 
Objective-C for Beginners
Objective-C for BeginnersObjective-C for Beginners
Objective-C for Beginners
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency Gotchas
 
Swift 3 Programming for iOS : subscript init
Swift 3 Programming for iOS : subscript initSwift 3 Programming for iOS : subscript init
Swift 3 Programming for iOS : subscript init
 
Python for text processing
Python for text processingPython for text processing
Python for text processing
 
Python introduction
Python introductionPython introduction
Python introduction
 
Cleanup and new optimizations in WPython 1.1
Cleanup and new optimizations in WPython 1.1Cleanup and new optimizations in WPython 1.1
Cleanup and new optimizations in WPython 1.1
 
PyFoursquare: Python Library for Foursquare
PyFoursquare: Python Library for FoursquarePyFoursquare: Python Library for Foursquare
PyFoursquare: Python Library for Foursquare
 

Destaque

Loosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain modelLoosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain modelFrancesca1980
 
Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascriptFrancesca1980
 
Michelle Hathaway Mastery Timeline
Michelle Hathaway Mastery TimelineMichelle Hathaway Mastery Timeline
Michelle Hathaway Mastery TimelineMichelle Hathaway
 
ΑΠΟΓΡΑΦΗ
ΑΠΟΓΡΑΦΗΑΠΟΓΡΑΦΗ
ΑΠΟΓΡΑΦΗsteverz
 
Writing cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI BindingsWriting cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI BindingsFrancesca1980
 
Trabajo en equipo abierto 4hrs 23 noviembre tlc
Trabajo en equipo abierto 4hrs 23 noviembre tlcTrabajo en equipo abierto 4hrs 23 noviembre tlc
Trabajo en equipo abierto 4hrs 23 noviembre tlcCinet México
 

Destaque (8)

Advanced JQuery
 Advanced JQuery Advanced JQuery
Advanced JQuery
 
Loosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain modelLoosely Coupled Complexity - Unleash the power of your domain model
Loosely Coupled Complexity - Unleash the power of your domain model
 
Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascript
 
Michelle Hathaway Mastery Timeline
Michelle Hathaway Mastery TimelineMichelle Hathaway Mastery Timeline
Michelle Hathaway Mastery Timeline
 
ΑΠΟΓΡΑΦΗ
ΑΠΟΓΡΑΦΗΑΠΟΓΡΑΦΗ
ΑΠΟΓΡΑΦΗ
 
Open Education Resources
Open Education ResourcesOpen Education Resources
Open Education Resources
 
Writing cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI BindingsWriting cool web 2.0 apps with GWT and UI Bindings
Writing cool web 2.0 apps with GWT and UI Bindings
 
Trabajo en equipo abierto 4hrs 23 noviembre tlc
Trabajo en equipo abierto 4hrs 23 noviembre tlcTrabajo en equipo abierto 4hrs 23 noviembre tlc
Trabajo en equipo abierto 4hrs 23 noviembre tlc
 

Semelhante a Java scriptpatterns

Websockets, Ruby y Pusher Webprendedor 2010
Websockets, Ruby y Pusher Webprendedor 2010Websockets, Ruby y Pusher Webprendedor 2010
Websockets, Ruby y Pusher Webprendedor 2010Ismael Celis
 
The Not Java That's Not Scala
The Not Java That's Not ScalaThe Not Java That's Not Scala
The Not Java That's Not ScalaJustin Lee
 
Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010Matt Aimonetti
 
MongoDB on Rails (and Ruby)
MongoDB on Rails (and Ruby)MongoDB on Rails (and Ruby)
MongoDB on Rails (and Ruby)jan_mindmatters
 
D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4Jan Berdajs
 
Advanced android
Advanced androidAdvanced android
Advanced androiddonnfelker
 
Javascript the Interlingua of the Web
Javascript the Interlingua of the WebJavascript the Interlingua of the Web
Javascript the Interlingua of the Webandersjanmyr
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryRebecca Murphey
 
The Mobile Web @ 2010 JSConf
The Mobile Web @ 2010 JSConfThe Mobile Web @ 2010 JSConf
The Mobile Web @ 2010 JSConfdion
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code OrganizationRebecca Murphey
 
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdfAndrey Breslav
 
Objective-C for Java Developers
Objective-C for Java DevelopersObjective-C for Java Developers
Objective-C for Java DevelopersBob McCune
 
Using Templates to Achieve Awesomer Architecture
Using Templates to Achieve Awesomer ArchitectureUsing Templates to Achieve Awesomer Architecture
Using Templates to Achieve Awesomer ArchitectureGarann Means
 
ZOMG WHY IS THIS CODE SO SLOW
ZOMG WHY IS THIS CODE SO SLOWZOMG WHY IS THIS CODE SO SLOW
ZOMG WHY IS THIS CODE SO SLOWAaron Patterson
 

Semelhante a Java scriptpatterns (17)

µServices
µServicesµServices
µServices
 
Websockets, Ruby y Pusher Webprendedor 2010
Websockets, Ruby y Pusher Webprendedor 2010Websockets, Ruby y Pusher Webprendedor 2010
Websockets, Ruby y Pusher Webprendedor 2010
 
The Not Java That's Not Scala
The Not Java That's Not ScalaThe Not Java That's Not Scala
The Not Java That's Not Scala
 
Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010Macruby - RubyConf Presentation 2010
Macruby - RubyConf Presentation 2010
 
MongoDB on Rails (and Ruby)
MongoDB on Rails (and Ruby)MongoDB on Rails (and Ruby)
MongoDB on Rails (and Ruby)
 
D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4
 
Advanced android
Advanced androidAdvanced android
Advanced android
 
Javascript the Interlingua of the Web
Javascript the Interlingua of the WebJavascript the Interlingua of the Web
Javascript the Interlingua of the Web
 
The jQuery Divide
The jQuery DivideThe jQuery Divide
The jQuery Divide
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
 
The Mobile Web @ 2010 JSConf
The Mobile Web @ 2010 JSConfThe Mobile Web @ 2010 JSConf
The Mobile Web @ 2010 JSConf
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code Organization
 
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
2022 May - Shoulders of Giants - Amsterdam - Kotlin Dev Day.pdf
 
Objective-C for Java Developers
Objective-C for Java DevelopersObjective-C for Java Developers
Objective-C for Java Developers
 
Meet Couch DB
Meet Couch DBMeet Couch DB
Meet Couch DB
 
Using Templates to Achieve Awesomer Architecture
Using Templates to Achieve Awesomer ArchitectureUsing Templates to Achieve Awesomer Architecture
Using Templates to Achieve Awesomer Architecture
 
ZOMG WHY IS THIS CODE SO SLOW
ZOMG WHY IS THIS CODE SO SLOWZOMG WHY IS THIS CODE SO SLOW
ZOMG WHY IS THIS CODE SO SLOW
 

Mais de Francesca1980

Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascriptFrancesca1980
 
Simple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computingSimple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computingFrancesca1980
 
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScriptPhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScriptFrancesca1980
 
Programmazione web libera dai framework
Programmazione web libera dai frameworkProgrammazione web libera dai framework
Programmazione web libera dai frameworkFrancesca1980
 

Mais de Francesca1980 (6)

Map meshup
Map meshupMap meshup
Map meshup
 
Java scriptpatterns
Java scriptpatternsJava scriptpatterns
Java scriptpatterns
 
Event driven javascript
Event driven javascriptEvent driven javascript
Event driven javascript
 
Simple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computingSimple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computing
 
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScriptPhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
PhoneGap ovvero lo Sviluppo Mobile Nativo con HTML, CSS e JavaScript
 
Programmazione web libera dai framework
Programmazione web libera dai frameworkProgrammazione web libera dai framework
Programmazione web libera dai framework
 

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. giordano.scalzo@cleancode.it @giordanoscalzo www.slideshare.net/giordano github.com/gscalzo Wednesday, November 10, 2010