KEMBAR78
Design patterns in javascript | PPTX
Design patterns in Javascript


           Miao Siyu
Why need design patterns

• Easy & nature: read, use/follow, extend/re-
  use, co-operator(expose api, split work…)…

• Efficiency & memory cost/gc…
books
• 'Patterns Of Enterprise Application
  Architecture' Martin Fowler
• 'JavaScript Patterns' Stoyan Stefanov
• 'Pro JavaScript Design Patterns' Ross Harmes
  and Dustin Diaz
• 'Learning JavaScript Design Patterns' Addy
  Osmani
• …
Categories Of Design Pattern
• Creational Design Patterns
  Constructor, Factory, Abstract, Prototype, Singleton and Builder

• Structural Design Patterns
  Decorator, Facade, Flyweight, Adapter and Proxy

• Behavioral Design Patterns
  Iterator, Mediator, Observer and Visitor
Create an object
   • var newObject = {};
   • var newObject = Object.create(…);
   • var newObject = new Class();




http://dmitrysoshnikov.com/ecmascript/javascript-the-core/
Define properties
• newObject.someKey = …;
• newObject*“someKey”+ = …;
• Object.defineProperty(newObject, “someKey”,,
     // property attributes here: value, writable…
  })
• function Car(model, color){
     this.model = model;
     this.color = color
  }
  Car.prototype.run = function(),console.log(“run”)-;
Prototype pattern
• var anotherCar = Object.create( someCar );
• var beget = (function () {
     function F() {};
     return function (proto) {
        F.prototype = proto;
        return new F();
     };
  })();         Clone using prototype: avoid the inherent cost
Singleton pattern
var Singleton = (function () { Anonymous Function
          var instantiated;
          function init() {
                    return {
                               publicMethod: function () {},
                               publicProperty: 'test'
                    };
          }
          return {
                    getInstance: function () {
                               if (!instantiated) {
                                           instantiated = init();
                               }
                               return instantiated;
                    }
          };
})();              Singleton.getInstance().publicMethod();
Module pattern
                                                               Loose Augumentation:

var myNamespace = (function () {                               var MODULE = (function (my) {
         var myPrivateVar = 0;                                         // add capabilities...
         var myPrivateMethod = function (someText) {                   return my;
                    console.log(someText);                     }(MODULE || {}));
         };                                              Option 1: var myApplication = myApplication || {};
                                                         Option 2 if(!MyApplication) MyApplication = {};
         return {                                        Option 3: var myApplication = myApplication = myApplication || {}
                                                         Option 4: myApplication || (myApplication = {});
                    myPublicVar: "foo",                  Option 5: var myApplication = myApplication === undefined ? {} :
                                                         myApplication;
                    myPublicFunction: function (bar) {
                                myPrivateVar++;                Cloning & Inheritance
                                myPrivateMethod(bar);
                                                               for (key in old) {
                    }
                                                                  if (old.hasOwnProperty(key)) {
         };
                                                                     my[key] = old[key];
})();                                                             }
                                                                }


         http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
The Revealing Module Pattern
var myRevealingModule = (function(){
       var name = 'John Smith';
       function setPerson (personName) {
                name = personName;
       }
       function getPerson () {
                                     Advantage: same style
                return name;
       }                             Disadvantage: when over-writting
       return {
                // set: setPerson,
                get: getPerson
       };
}());
Observer Pattern & Mediator Pattern
var pubsub = {};                           q.subscribe = function( topic, func ) {   q.unsubscribe = function( token ) {
(function(q) {                               if (!topics[topic]) {                      for ( var m in topics ) {
 var topics = {},                              topics[topic] = [];                        if ( topics[m] ) {
 subUid = -1;                                }                                              for (var i = 0, j = topics[m].length; i < j; i++) {
 q.publish = function( topic, args ) {       var token = (++subUid).toString();               if (topics[m][i].token === token) {
                                               topics[topic].push({                             topics[m].splice(i, 1);
  if ( !topics[topic] ) {                       token: token,                                   return token;
    return false;                               func: func                                    }
  }                                            });                                          }
  var subscribers = topics[topic],           return token;                                }
  var tempArr;                             };                                           }
                                                                                        return this;
  if(subscribers ) {                                                                  };
     tempArr = subscribers .slice(0);                                                }( pubsub ));
     while (tempArr .length) {
        tempArr.pop().func(topic, args);
     }
  }
                                                    Backbone.js: listen to changes in model
  return this;
 };

             Mediator Pattern: Colleague – communicate by -> Mediator
            Observer - listener to -> Mediator
Mediator:
Communication between Colleague




                     Façade: N-to-1, listener to a event hub
Command Pattern
(function(){
   var CarManager = {
      requestInfo: function( model, id ){},
      buyVehicle: function( model, id ){},
      arrangeViewing: function( model, id ){}
   };
                                                           We can keep track of the commands,
})();                                                           also record a game reply
           CarManager.execute("arrangeViewing", "Ferrari", "14523");
           CarManager.execute("requestInfo", "Ford Escort", "34232");
           CarManager.execute("buyVehicle", "Ford Escort", "34232");


CarManager.execute = function (name) {
   // we can log the commands here, also implements an undo function
   return CarManager[name] && CarManager[name].apply(CarManager, [].slice.call(arguments, 1));
};
Façade Pattern
                                            function setStyles(elements, styles) {
var foo = document.getElementById('foo');    for (var i=0, length = elements.length; i < length; i++) {
foo.style.color = 'red';                      var element = document.getElementById(elements[i]);
foo.style.width = '150px';
                                              for (var property in styles) {
var bar = document.getElementById('bar');      element.style[property] = styles[property];
                                              }
 bar.style.color = 'red';
                                             }
 bar.style.width = '150px';
                                            }

var baz = document.getElementById('baz');   //Now you can just write this:
baz.style.color = 'red';                    setStyles(['foo', 'bar', 'baz'], {
baz.style.width = '150px';                   color: 'red',
                                             width: '150px'
                                            });


             Very common in Jquery: .css(), .animate()…
Factory Pattern
var AbstractVehicleFactory = (function () {
            var types = {};
            return {
                         getVehicle: function (type, customizations) {
                                      // we can keep track of vehicle or get vehicle by options instead of type …
                                      var Vehicle = types[type];
                                      return (Vehicle) ? return new Vehicle(customizations) : null;
                         },
                         registerVehicle: function (type, Vehicle) {
                                      var proto = Vehicle.prototype;
                                      if (proto.drive && proto.breakDown) {
                                                    types[type] = Vehicle;
                                      }
                                      return AbstractVehicleFactory;
                         }
            };
})();

AbstractVehicleFactory.registerVehicle("car", Car);                        Give me a android phone with
AbstractVehicleFactory.registerVehicle("truck", Truck);                     4.1 inch screen around S$400
var car = AbstractVehicleFactory.getVehicle("car", { color: "yellow", turbo: true });
var truck = AbstractVehicleFactory.getVehicle("truck", { monster: true, cylinders: 12 });
Mixin Pattern
function augment( receivingClass, givingClass ) {        var Car = function( settings ){
  if ( arguments[2] ) {                                              this.model = settings.model ;
     for (var i=2, len=arguments.length; i<len; i++) {               this.colour = settings.colour ;
        receivingClass.prototype[arguments[i]] =         };
           givingClass.prototype[arguments[i]];
     }                                                   var Mixin = function(){};
  }
                                                         Mixin.prototype = {
  else {
                                                                    driveForward: function(){},
     for ( var methodName in givingClass.prototype ) {
        if ( !receivingClass.prototype[methodName] ) {
                                                                    driveBackward: function(){}
           receivingClass.prototype[methodName] =        };
               givingClass.prototype[methodName];
        }                                                augment( Car, Mixin,'driveForward','driveBackward' );
     }
  }                                                      var vehicle = new Car({model:'Ford', colour:'blue'});
}
                                                         vehicle.driveForward();
                                                         vehicle.driveBackward();



   We have update our factory to produce                       Class level
         tanks with new weapon
Decorator Pattern
• SubClassing
 var Person = function( firstName , lastName ){                         Object level
           this.firstName = firstName;
           this.lastName = lastName;
           this.gender = 'male'
 };

 var Superhero = function( firstName, lastName , powers ){
           Person.call(this, firstName, lastName);
           this.powers = powers;
 }
 SuperHero.prototype = Object.create(Person.prototype);

 var superman = new Superhero( "Clark" ,"Kent" , ['flight','heat-vision'] );
• Simple decorator                               • Mulit decorator
function Vehicle( vehicleType ){
                                             function MacBook() {
  this.vehicleType = vehicleType || 'car',     this.cost = function () { return 997; };
  this.model = 'default',                      this.screenSize = function () { return 13.3; };
  this.license = '00000-000'                 }
}                                            function Memory( macbook ) {
function makeTruck(truck){                     var v = macbook.cost();
  truck.setModel =function( modelName ){}      macbook.cost = function() { return v + 75 ;}
                                             }
  truck.setColor = function( color ){}       function LargeScreen( macbook ){
  return truck;                                var v = macbook.cost();
}                                              macbook.cost = function(){ return v + 100; };
                                               macbook.screenSize=function(){ return 14.8; };
var truck = makeTruck(new Vehicle());        }
                                             function Insurance( macbook ){
                                             var v = macbook.cost();
                                               macbook.cost = function(){ return v + 250; };
                                             }

                                             var mb = new MacBook();
                                             Memory(mb);
                                             LargeScreen(mb);
                                             Insurance(mb);
   user can wear equips to change attr
          and gain new ablitities
Pseudo-classical decorators: interface
var TodoList = new Interface('Composite', ['add', 'remove']);
var TodoItem = new Interface('TodoItem', ['save']);

var myTodoList = function(id, method, action) {
   // implements TodoList, TodoItem
};
                                                         Make sure that only archers
function addTodo( todoInstance ) {                         can enter certain stage
  Interface.ensureImplements(todoInstance, TodoList, TodoItem);
  // …
}

https://gist.github.com/1057989
var Interface = function(name, methods),…-
Interface.ensureImplements = function(obj),…-
Flyweight pattern
var Book = function(){                      Book info:
   this.id = id;                            var Book = function () {
   this.title = title;                         this.title = title;
   this.author = author;                       this.author = author;
   this.genre = genre;                         this.genre = genre;
   this.pageCount = pageCount;                 this.pageCount = pageCount;
   this.publisherID = publisherID;             this.publisherID = publisherID;
   this.ISBN = ISBN;                           this.ISBN = ISBN;
   this.checkoutDate = checkoutDate;        };
   this.checkoutMember = checkoutMember;
   this.dueReturnDate = dueReturnDate;
   this.availability = availability;                   Checkout Info:
};


                      Share date as much as possible
var BookRecordManager = (function () {
var BookFactory = (function () {                     var bookRecordDatabase = {};
    var existingBooks = {};                          return {
    return {
      createBook: function () {                               addBookRecord: function (
         var existingBook = existingBooks[ISBN];                 var book = bookFactory.createBook();
         if (existingBook) {                                     bookRecordDatabase[id] = {
            return existingBook;                                    checkoutMember: checkoutMember,
         } else {                                                   checkoutDate: checkoutDate,
            var book = new Book();                                  dueReturnDate: dueReturnDate,
            existingBooks[ISBN] = book;                             availability: availability,
            return book;                                            book: book
         }                                                       };
      }                                                       },
    }
});                                                           updateCheckoutStatus: function () {},
                                                              extendCheckoutPeriod: function () {},
                                                              isPastDue: function (bookID) {}
                                                         };
                                                   });
Object Pool
Pool = {arr:[]};

Pool.pop = function(){
  if(Pool.arr.length > 0){
     return Pool.arr.pop().wake();
  }else{
     return new Obj();
  }
}                                                 May have hundreds of planes through the
Pool.push= function(obj){                         whole game, but not more than 20 at
                                                  the same time.
  Pool.arr.push(obj);
  obj.sleep();                                    Generator a plan: pop()
}                                                 Leave screen or destroyed: push()
Object pools are used to avoid the instantiation
cost of creating new objects by re-using existing
ones. Avoid creating objects is gc-friendly.      Reuse resource when it has a high cost to
                                                  make or release, eg. connection pool
MV* pattern
• V: Templing
        Handlebars, Underscore…
• *: bind event, route, render, data-binding…
• C: flex, extendable, suit for big project
        Backbone, Spine…
• P: Present Model -> View, view no direct access to model,
  safer then MVC
        Backbone , Angular…
• VM: VM & V more tightly, suit small project
        Knockout…


TODO MVC http://todomvc.com/
Namespace
     • Automating nested namespacing
                        // automatic namespacing
                        var myApp = myApp || {};
var application = {
 utilities:{            function extend( ns, ns_string ) {
   drawing:{              var parts = ns_string.split('.'),
     canvas:{             parent = ns,
       2d:{}              pl, i;
     }                    pl = parts.length;
   }                      for (i = 0; i < pl; i++) {
 }                          if (typeof parent[parts[i]] == 'undefined') {
};                            parent[parts[i]] = {};
                            }
                            parent = parent[parts[i]];
                          }
                          return parent;
                        }

                        var mod = extend(myApp, 'myApp.modules.module2');
• Deep object extension
function extend(destination, source) {
 var toString = Object.prototype.toString,
 objTest = toString.call({});
 for (var property in source) {
   if (source[property] && objTest == toString.call(source[property])) {
     destination[property] = destination[property] || {};
     extend(destination[property], source[property]);
   } else {
     destination[property] = source[property];
   }
 }
 return destination;
};


  Jquery.extend
Design pattern in JQuery core
• Adapter pattern
       .css({opacity:.5})
• Façade pattern
       .ajax()
• Observe pattern
       .on(event, cssSelector, func)
• Iterator pattern
       array is also object
• Proxy pattern
       .proxy(function(),this…-, thisObj) control before sth really
loaded
• Builder Pattern
       $(“<a>a link</a>”).appendTo(…) xml initing
Modular JS
• AMD
• CMD        Script loaders
• Harmony
AMD
•   Asynchronous Module Definition, Commonjs
•   RequireJS
•   define(moduleID, [dependencies], definition function)
•   require([dependencies], function)

     https://github.com/amdjs/amdjs-api/wiki/AMD
CMD
 • require()
 • Exports                               http://wiki.commonjs.org/wiki/Modules/Wrappings

cmd: Common Module Definition

Sea.js   define(function(require, exports, module) { // The module code goes here });



• Modules are singletons.
• New free variables within the module scope should not be introduced.
• Execution must be lazy, import can be later: define(dependency, …) vs.
  define(function(require(…))
• With some care, modules may have cyclic dependencies.
harmony
• Export
• Import
• Module

Design patterns in javascript

  • 1.
    Design patterns inJavascript Miao Siyu
  • 2.
    Why need designpatterns • Easy & nature: read, use/follow, extend/re- use, co-operator(expose api, split work…)… • Efficiency & memory cost/gc…
  • 3.
    books • 'Patterns OfEnterprise Application Architecture' Martin Fowler • 'JavaScript Patterns' Stoyan Stefanov • 'Pro JavaScript Design Patterns' Ross Harmes and Dustin Diaz • 'Learning JavaScript Design Patterns' Addy Osmani • …
  • 4.
    Categories Of DesignPattern • Creational Design Patterns Constructor, Factory, Abstract, Prototype, Singleton and Builder • Structural Design Patterns Decorator, Facade, Flyweight, Adapter and Proxy • Behavioral Design Patterns Iterator, Mediator, Observer and Visitor
  • 5.
    Create an object • var newObject = {}; • var newObject = Object.create(…); • var newObject = new Class(); http://dmitrysoshnikov.com/ecmascript/javascript-the-core/
  • 6.
    Define properties • newObject.someKey= …; • newObject*“someKey”+ = …; • Object.defineProperty(newObject, “someKey”,, // property attributes here: value, writable… }) • function Car(model, color){ this.model = model; this.color = color } Car.prototype.run = function(),console.log(“run”)-;
  • 7.
    Prototype pattern • varanotherCar = Object.create( someCar ); • var beget = (function () { function F() {}; return function (proto) { F.prototype = proto; return new F(); }; })(); Clone using prototype: avoid the inherent cost
  • 8.
    Singleton pattern var Singleton= (function () { Anonymous Function var instantiated; function init() { return { publicMethod: function () {}, publicProperty: 'test' }; } return { getInstance: function () { if (!instantiated) { instantiated = init(); } return instantiated; } }; })(); Singleton.getInstance().publicMethod();
  • 9.
    Module pattern Loose Augumentation: var myNamespace = (function () { var MODULE = (function (my) { var myPrivateVar = 0; // add capabilities... var myPrivateMethod = function (someText) { return my; console.log(someText); }(MODULE || {})); }; Option 1: var myApplication = myApplication || {}; Option 2 if(!MyApplication) MyApplication = {}; return { Option 3: var myApplication = myApplication = myApplication || {} Option 4: myApplication || (myApplication = {}); myPublicVar: "foo", Option 5: var myApplication = myApplication === undefined ? {} : myApplication; myPublicFunction: function (bar) { myPrivateVar++; Cloning & Inheritance myPrivateMethod(bar); for (key in old) { } if (old.hasOwnProperty(key)) { }; my[key] = old[key]; })(); } } http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
  • 10.
    The Revealing ModulePattern var myRevealingModule = (function(){ var name = 'John Smith'; function setPerson (personName) { name = personName; } function getPerson () { Advantage: same style return name; } Disadvantage: when over-writting return { // set: setPerson, get: getPerson }; }());
  • 11.
    Observer Pattern &Mediator Pattern var pubsub = {}; q.subscribe = function( topic, func ) { q.unsubscribe = function( token ) { (function(q) { if (!topics[topic]) { for ( var m in topics ) { var topics = {}, topics[topic] = []; if ( topics[m] ) { subUid = -1; } for (var i = 0, j = topics[m].length; i < j; i++) { q.publish = function( topic, args ) { var token = (++subUid).toString(); if (topics[m][i].token === token) { topics[topic].push({ topics[m].splice(i, 1); if ( !topics[topic] ) { token: token, return token; return false; func: func } } }); } var subscribers = topics[topic], return token; } var tempArr; }; } return this; if(subscribers ) { }; tempArr = subscribers .slice(0); }( pubsub )); while (tempArr .length) { tempArr.pop().func(topic, args); } } Backbone.js: listen to changes in model return this; }; Mediator Pattern: Colleague – communicate by -> Mediator Observer - listener to -> Mediator
  • 12.
    Mediator: Communication between Colleague Façade: N-to-1, listener to a event hub
  • 13.
    Command Pattern (function(){ var CarManager = { requestInfo: function( model, id ){}, buyVehicle: function( model, id ){}, arrangeViewing: function( model, id ){} }; We can keep track of the commands, })(); also record a game reply CarManager.execute("arrangeViewing", "Ferrari", "14523"); CarManager.execute("requestInfo", "Ford Escort", "34232"); CarManager.execute("buyVehicle", "Ford Escort", "34232"); CarManager.execute = function (name) { // we can log the commands here, also implements an undo function return CarManager[name] && CarManager[name].apply(CarManager, [].slice.call(arguments, 1)); };
  • 14.
    Façade Pattern function setStyles(elements, styles) { var foo = document.getElementById('foo'); for (var i=0, length = elements.length; i < length; i++) { foo.style.color = 'red'; var element = document.getElementById(elements[i]); foo.style.width = '150px'; for (var property in styles) { var bar = document.getElementById('bar'); element.style[property] = styles[property]; } bar.style.color = 'red'; } bar.style.width = '150px'; } var baz = document.getElementById('baz'); //Now you can just write this: baz.style.color = 'red'; setStyles(['foo', 'bar', 'baz'], { baz.style.width = '150px'; color: 'red', width: '150px' }); Very common in Jquery: .css(), .animate()…
  • 15.
    Factory Pattern var AbstractVehicleFactory= (function () { var types = {}; return { getVehicle: function (type, customizations) { // we can keep track of vehicle or get vehicle by options instead of type … var Vehicle = types[type]; return (Vehicle) ? return new Vehicle(customizations) : null; }, registerVehicle: function (type, Vehicle) { var proto = Vehicle.prototype; if (proto.drive && proto.breakDown) { types[type] = Vehicle; } return AbstractVehicleFactory; } }; })(); AbstractVehicleFactory.registerVehicle("car", Car); Give me a android phone with AbstractVehicleFactory.registerVehicle("truck", Truck); 4.1 inch screen around S$400 var car = AbstractVehicleFactory.getVehicle("car", { color: "yellow", turbo: true }); var truck = AbstractVehicleFactory.getVehicle("truck", { monster: true, cylinders: 12 });
  • 16.
    Mixin Pattern function augment(receivingClass, givingClass ) { var Car = function( settings ){ if ( arguments[2] ) { this.model = settings.model ; for (var i=2, len=arguments.length; i<len; i++) { this.colour = settings.colour ; receivingClass.prototype[arguments[i]] = }; givingClass.prototype[arguments[i]]; } var Mixin = function(){}; } Mixin.prototype = { else { driveForward: function(){}, for ( var methodName in givingClass.prototype ) { if ( !receivingClass.prototype[methodName] ) { driveBackward: function(){} receivingClass.prototype[methodName] = }; givingClass.prototype[methodName]; } augment( Car, Mixin,'driveForward','driveBackward' ); } } var vehicle = new Car({model:'Ford', colour:'blue'}); } vehicle.driveForward(); vehicle.driveBackward(); We have update our factory to produce Class level tanks with new weapon
  • 17.
    Decorator Pattern • SubClassing var Person = function( firstName , lastName ){ Object level this.firstName = firstName; this.lastName = lastName; this.gender = 'male' }; var Superhero = function( firstName, lastName , powers ){ Person.call(this, firstName, lastName); this.powers = powers; } SuperHero.prototype = Object.create(Person.prototype); var superman = new Superhero( "Clark" ,"Kent" , ['flight','heat-vision'] );
  • 18.
    • Simple decorator • Mulit decorator function Vehicle( vehicleType ){ function MacBook() { this.vehicleType = vehicleType || 'car', this.cost = function () { return 997; }; this.model = 'default', this.screenSize = function () { return 13.3; }; this.license = '00000-000' } } function Memory( macbook ) { function makeTruck(truck){ var v = macbook.cost(); truck.setModel =function( modelName ){} macbook.cost = function() { return v + 75 ;} } truck.setColor = function( color ){} function LargeScreen( macbook ){ return truck; var v = macbook.cost(); } macbook.cost = function(){ return v + 100; }; macbook.screenSize=function(){ return 14.8; }; var truck = makeTruck(new Vehicle()); } function Insurance( macbook ){ var v = macbook.cost(); macbook.cost = function(){ return v + 250; }; } var mb = new MacBook(); Memory(mb); LargeScreen(mb); Insurance(mb); user can wear equips to change attr and gain new ablitities
  • 19.
    Pseudo-classical decorators: interface varTodoList = new Interface('Composite', ['add', 'remove']); var TodoItem = new Interface('TodoItem', ['save']); var myTodoList = function(id, method, action) { // implements TodoList, TodoItem }; Make sure that only archers function addTodo( todoInstance ) { can enter certain stage Interface.ensureImplements(todoInstance, TodoList, TodoItem); // … } https://gist.github.com/1057989 var Interface = function(name, methods),…- Interface.ensureImplements = function(obj),…-
  • 20.
    Flyweight pattern var Book= function(){ Book info: this.id = id; var Book = function () { this.title = title; this.title = title; this.author = author; this.author = author; this.genre = genre; this.genre = genre; this.pageCount = pageCount; this.pageCount = pageCount; this.publisherID = publisherID; this.publisherID = publisherID; this.ISBN = ISBN; this.ISBN = ISBN; this.checkoutDate = checkoutDate; }; this.checkoutMember = checkoutMember; this.dueReturnDate = dueReturnDate; this.availability = availability; Checkout Info: }; Share date as much as possible
  • 21.
    var BookRecordManager =(function () { var BookFactory = (function () { var bookRecordDatabase = {}; var existingBooks = {}; return { return { createBook: function () { addBookRecord: function ( var existingBook = existingBooks[ISBN]; var book = bookFactory.createBook(); if (existingBook) { bookRecordDatabase[id] = { return existingBook; checkoutMember: checkoutMember, } else { checkoutDate: checkoutDate, var book = new Book(); dueReturnDate: dueReturnDate, existingBooks[ISBN] = book; availability: availability, return book; book: book } }; } }, } }); updateCheckoutStatus: function () {}, extendCheckoutPeriod: function () {}, isPastDue: function (bookID) {} }; });
  • 22.
    Object Pool Pool ={arr:[]}; Pool.pop = function(){ if(Pool.arr.length > 0){ return Pool.arr.pop().wake(); }else{ return new Obj(); } } May have hundreds of planes through the Pool.push= function(obj){ whole game, but not more than 20 at the same time. Pool.arr.push(obj); obj.sleep(); Generator a plan: pop() } Leave screen or destroyed: push() Object pools are used to avoid the instantiation cost of creating new objects by re-using existing ones. Avoid creating objects is gc-friendly. Reuse resource when it has a high cost to make or release, eg. connection pool
  • 23.
    MV* pattern • V:Templing Handlebars, Underscore… • *: bind event, route, render, data-binding… • C: flex, extendable, suit for big project Backbone, Spine… • P: Present Model -> View, view no direct access to model, safer then MVC Backbone , Angular… • VM: VM & V more tightly, suit small project Knockout… TODO MVC http://todomvc.com/
  • 24.
    Namespace • Automating nested namespacing // automatic namespacing var myApp = myApp || {}; var application = { utilities:{ function extend( ns, ns_string ) { drawing:{ var parts = ns_string.split('.'), canvas:{ parent = ns, 2d:{} pl, i; } pl = parts.length; } for (i = 0; i < pl; i++) { } if (typeof parent[parts[i]] == 'undefined') { }; parent[parts[i]] = {}; } parent = parent[parts[i]]; } return parent; } var mod = extend(myApp, 'myApp.modules.module2');
  • 25.
    • Deep objectextension function extend(destination, source) { var toString = Object.prototype.toString, objTest = toString.call({}); for (var property in source) { if (source[property] && objTest == toString.call(source[property])) { destination[property] = destination[property] || {}; extend(destination[property], source[property]); } else { destination[property] = source[property]; } } return destination; }; Jquery.extend
  • 26.
    Design pattern inJQuery core • Adapter pattern .css({opacity:.5}) • Façade pattern .ajax() • Observe pattern .on(event, cssSelector, func) • Iterator pattern array is also object • Proxy pattern .proxy(function(),this…-, thisObj) control before sth really loaded • Builder Pattern $(“<a>a link</a>”).appendTo(…) xml initing
  • 27.
    Modular JS • AMD •CMD Script loaders • Harmony
  • 28.
    AMD • Asynchronous Module Definition, Commonjs • RequireJS • define(moduleID, [dependencies], definition function) • require([dependencies], function) https://github.com/amdjs/amdjs-api/wiki/AMD
  • 29.
    CMD • require() • Exports http://wiki.commonjs.org/wiki/Modules/Wrappings cmd: Common Module Definition Sea.js define(function(require, exports, module) { // The module code goes here }); • Modules are singletons. • New free variables within the module scope should not be introduced. • Execution must be lazy, import can be later: define(dependency, …) vs. define(function(require(…)) • With some care, modules may have cyclic dependencies.
  • 30.