javascript patterns

139
Giordano Scalzo JavaScript Patterns Wednesday, November 10, 2010

Post on 23-Sep-2014

16 views

Category:

Technology


0 download

DESCRIPTION

Write JavaScript like a pro!

TRANSCRIPT

Page 1: JavaScript Patterns

Giordano Scalzo

JavaScript Patterns

Wednesday, November 10, 2010

Page 2: JavaScript Patterns

I’m not a guru!

Wednesday, November 10, 2010

Page 3: JavaScript Patterns

I’m still learning

Wednesday, November 10, 2010

Page 4: JavaScript Patterns

Why?

Wednesday, November 10, 2010

Page 5: JavaScript Patterns

JavaScript isn’t this anymore

Wednesday, November 10, 2010

Page 6: JavaScript Patterns

JavaScript is everywhere!

Wednesday, November 10, 2010

Page 7: JavaScript Patterns

Technology Radar

JavaScript is trendy!

Wednesday, November 10, 2010

Page 8: JavaScript Patterns

Technology Radar

JavaScript is trendy!

Wednesday, November 10, 2010

Page 9: JavaScript Patterns

At the beginning...

Wednesday, November 10, 2010

Page 10: JavaScript Patterns

Hacked by Brendan Eich in one week...

Wednesday, November 10, 2010

Page 11: JavaScript Patterns

Former Mocha, renamed to JavaScript by Netscape

Wednesday, November 10, 2010

Page 12: JavaScript Patterns

after a while...

Wednesday, November 10, 2010

Page 13: JavaScript Patterns

and...

Wednesday, November 10, 2010

Page 14: JavaScript Patterns

:-(

Wednesday, November 10, 2010

Page 15: JavaScript Patterns

and so...

Wednesday, November 10, 2010

Page 16: JavaScript Patterns

Back to study!

Wednesday, November 10, 2010

Page 17: JavaScript Patterns

Started a notebook...

Wednesday, November 10, 2010

Page 18: JavaScript Patterns

Essential

Scope

Wednesday, November 10, 2010

Page 19: JavaScript Patterns

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

{antipattern}Wednesday, November 10, 2010

Page 20: JavaScript Patterns

Global variables are evil!

Wednesday, November 10, 2010

Page 21: JavaScript Patterns

Variables clash

Wednesday, November 10, 2010

Page 22: JavaScript Patterns

Always declare variables with var

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

{pattern}Wednesday, November 10, 2010

Page 23: JavaScript Patterns

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

{antipattern}Wednesday, November 10, 2010

Page 24: JavaScript Patterns

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

{antipattern}

b become global

Wednesday, November 10, 2010

Page 25: JavaScript Patterns

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

don’t use assign chain in definition

{pattern}Wednesday, November 10, 2010

Page 26: JavaScript Patterns

function func(){ var a = 1,

b = 2, sum = a + b, myobject = {}, i, j;

// function body...}

{pattern}

Single var pattern

Wednesday, November 10, 2010

Page 27: JavaScript Patterns

Don’t forget comma otherwise...

Wednesday, November 10, 2010

Page 28: JavaScript Patterns

... variables become globals

Wednesday, November 10, 2010

Page 29: JavaScript Patterns

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

Page 30: JavaScript Patterns

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

Page 31: JavaScript Patterns

“Variables should be declared as close to their usage as possible”

Robert C. Martin - Clean Code

Against minimum vertical distance principle

Wednesday, November 10, 2010

Page 32: JavaScript Patterns

EssentialLiteral and Constructor

Wednesday, November 10, 2010

Page 33: JavaScript Patterns

In JavaScript almost everything is an object

Wednesday, November 10, 2010

Page 34: JavaScript Patterns

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

console.log(person.say());

It’s easy...

Wednesday, November 10, 2010

Page 35: JavaScript Patterns

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

console.log(person.say());

{antipattern}

but wrong! :-(

Wednesday, November 10, 2010

Page 36: JavaScript Patterns

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

console.log(person.say());

{pattern}Wednesday, November 10, 2010

Page 37: JavaScript Patterns

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

Page 38: JavaScript Patterns

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

Page 39: JavaScript Patterns

Duplication is evil!

Wednesday, November 10, 2010

Page 40: JavaScript Patterns

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

Custom Constructor Functions

{pattern}Wednesday, November 10, 2010

Page 41: JavaScript Patterns

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

Page 42: JavaScript Patterns

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());

So, at the end...

{pattern}Wednesday, November 10, 2010

Page 43: JavaScript Patterns

What if we forget new?

Wednesday, November 10, 2010

Page 44: JavaScript Patterns

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); //objectconsole.log(scott.name); // Scottconsole.log(typeof adam); //'undefined'console.log(window.name); // Adam

this will point to global object

Wednesday, November 10, 2010

Page 45: JavaScript Patterns

Enforce new pattern one: naming convention

Wednesday, November 10, 2010

Page 46: JavaScript Patterns

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); //Objectconsole.log(scott.name); // Scott

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

{pattern}Wednesday, November 10, 2010

Page 47: JavaScript Patterns

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); // undefinedconsole.log(adam.iamhumanbeing); // undefined

Wednesday, November 10, 2010

Page 48: JavaScript Patterns

Interm!zoPrototype property

Wednesday, November 10, 2010

Page 49: JavaScript Patterns

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

Page 50: JavaScript Patterns

foo

one: 1

__proto__

bar

three: 3

two: 2

Wednesday, November 10, 2010

Page 51: JavaScript Patterns

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

Behind the scenes...

Wednesday, November 10, 2010

Page 52: JavaScript Patterns

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); // Scottconsole.log(adam.name); // Adamconsole.log(scott.iamhumanbeing); // trueconsole.log(adam.iamhumanbeing); // true

Self invoking constructor

{pattern}Wednesday, November 10, 2010

Page 53: JavaScript Patterns

EssentialFunctions

Wednesday, November 10, 2010

Page 54: JavaScript Patterns

Functions as first class objects

Wednesday, November 10, 2010

Page 55: JavaScript Patterns

Immediate functions

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

Wednesday, November 10, 2010

Page 56: JavaScript Patterns

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

Page 57: JavaScript Patterns

Function scope

Wednesday, November 10, 2010

Page 58: JavaScript Patterns

// constructors function Parent(){}

function Child(){}

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

{antipattern}

5 globals...

Wednesday, November 10, 2010

Page 59: JavaScript Patterns

// global object var MYAPP = (function(){ var my = {}; // 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

{pattern}1 global!

Wednesday, November 10, 2010

Page 60: JavaScript Patterns

What about encapsulation?

Wednesday, November 10, 2010

Page 61: JavaScript Patterns

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

Page 62: JavaScript Patterns

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`

Create private member

{pattern}Wednesday, November 10, 2010

Page 63: JavaScript Patterns

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}

for methods too

Wednesday, November 10, 2010

Page 64: JavaScript Patterns

AdvancedCode reuse patterns

Wednesday, November 10, 2010

Page 65: JavaScript Patterns

vs

Classical vs prototypal inheritance

Wednesday, November 10, 2010

Page 66: JavaScript Patterns

Classical inheritancefunction 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

Page 67: JavaScript Patterns

new Parent()

name: Larry__proto__

Parent.prototypesay()

console.log(dad.say());

function(){ return 'My name is ' + this.name;};

Wednesday, November 10, 2010

Page 68: JavaScript Patterns

Default Classical Inheritance pattern

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

Wednesday, November 10, 2010

Page 69: JavaScript Patterns

new Parent()

name: Larry__proto__

Parent.prototypesay()

new Child()

name: Scott__proto__

console.log(kid.say());

function(){ return 'My name is ' + this.name;};

Wednesday, November 10, 2010

Page 70: JavaScript Patterns

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'

Drawback: it doesn’t call parent constructor

Wednesday, November 10, 2010

Page 71: JavaScript Patterns

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'

Drawback: it doesn’t call parent constructor

Wednesday, November 10, 2010

Page 72: JavaScript Patterns

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

Pattern Extension: rent a constructor

Wednesday, November 10, 2010

Page 73: JavaScript Patterns

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'

Pattern Extension: rent a constructor

Wednesday, November 10, 2010

Page 74: JavaScript Patterns

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'

Drawback: parent constructor is called twice

Wednesday, November 10, 2010

Page 75: JavaScript Patterns

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'

Drawback: parent constructor is called twice

Wednesday, November 10, 2010

Page 76: JavaScript Patterns

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'

Drawback: parent constructor is called twice

Wednesday, November 10, 2010

Page 77: JavaScript Patterns

mmmm let’s try with the same prototype

Wednesday, November 10, 2010

Page 78: JavaScript Patterns

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

Share the same prototype

Wednesday, November 10, 2010

Page 79: JavaScript Patterns

new Parent()

name: Larry__proto__

Parent.prototypesay()

new Child()

name: Scott__proto__

Wednesday, November 10, 2010

Page 80: JavaScript Patterns

Share the same prototype

Inheritance works as expectedConstructor called only onceLow memory footprint

Wednesday, November 10, 2010

Page 81: JavaScript Patterns

Share the same prototype

Child objects can affect other objects

Wednesday, November 10, 2010

Page 82: JavaScript Patterns

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

Enhance the pattern: temporary constructor

Wednesday, November 10, 2010

Page 83: JavaScript Patterns

new Parent()

name: Larry__proto__

Parent.prototypesay()

new Child()

name: Scott__proto__

new F()

__proto__

Wednesday, November 10, 2010

Page 84: JavaScript Patterns

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

The Holy Grail Pattern of classical inheritance

Wednesday, November 10, 2010

Page 85: JavaScript Patterns

We got it!

Wednesday, November 10, 2010

Page 86: JavaScript Patterns

What about Prototypal Inheritance?

Wednesday, November 10, 2010

Page 87: JavaScript Patterns

No more classes, only objects

Wednesday, November 10, 2010

Page 88: JavaScript Patterns

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

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

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

What we want in prototypal inheritance

Wednesday, November 10, 2010

Page 89: JavaScript Patterns

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

Prototypal inheritance function

Wednesday, November 10, 2010

Page 90: JavaScript Patterns

child = new F()

name: Larry__proto__

parent

name: Scottsay()

Wednesday, November 10, 2010

Page 91: JavaScript Patterns

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

Page 92: JavaScript Patterns

better classical or prototypal?

Wednesday, November 10, 2010

Page 93: JavaScript Patterns

It depends

Wednesday, November 10, 2010

Page 94: JavaScript Patterns

Goals of inheritance is reuse and reduce duplication

Wednesday, November 10, 2010

Page 95: JavaScript Patterns

isA relationship...Liskov principle...

difficult to tame inheritance...

Wednesday, November 10, 2010

Page 96: JavaScript Patterns

A modern and better approach is to use

Mix-In

Wednesday, November 10, 2010

Page 97: JavaScript Patterns

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

A beahviour...

Wednesday, November 10, 2010

Page 98: JavaScript Patterns

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

another beahviour...

Wednesday, November 10, 2010

Page 99: JavaScript Patterns

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

and an object...

Wednesday, November 10, 2010

Page 100: JavaScript Patterns

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 Foucaultvar xmlString = author.toXml();console.log(xmlString); //<name>Umberto Eco</name> // <book>Il nome della rosa</book> // <book>Il Pendolo di Focault</book>

result!

Wednesday, November 10, 2010

Page 101: JavaScript Patterns

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

givingClass.prototype[methodName]; } }}

The recipe

Wednesday, November 10, 2010

Page 102: JavaScript Patterns

AdvancedDesign Patterns

Wednesday, November 10, 2010

Page 103: JavaScript Patterns

Wednesday, November 10, 2010

Page 104: JavaScript Patterns

“A design pattern is a general reusable solution to a commonly occurring problem”

Wednesday, November 10, 2010

Page 105: JavaScript Patterns

JavaScript is not J@#*!

Wednesday, November 10, 2010

Page 106: JavaScript Patterns

creation of objectssubclasses decide which class to instantiate

Factory pattern

Wednesday, November 10, 2010

Page 107: JavaScript Patterns

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

Page 108: JavaScript Patterns

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();

A more concrete example...

Wednesday, November 10, 2010

Page 109: JavaScript Patterns

It seems lightly broken....

Wednesday, November 10, 2010

Page 110: JavaScript Patterns

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

Page 111: JavaScript Patterns

Chain of Responsibility pattern

Wednesday, November 10, 2010

Page 112: JavaScript Patterns

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

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

Extract condition and action....

Wednesday, November 10, 2010

Page 113: JavaScript Patterns

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

another condition and action....

Wednesday, November 10, 2010

Page 114: JavaScript Patterns

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

and last one condition and action....

Wednesday, November 10, 2010

Page 115: JavaScript Patterns

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);

and the engine!

Wednesday, November 10, 2010

Page 116: JavaScript Patterns

Or following the book...

Wednesday, November 10, 2010

Page 117: JavaScript Patterns

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; } };

Refactored an action...

Wednesday, November 10, 2010

Page 118: JavaScript Patterns

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; } };

other action...

Wednesday, November 10, 2010

Page 119: JavaScript Patterns

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; } };

last action...

Wednesday, November 10, 2010

Page 120: JavaScript Patterns

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);

and the engine!

Wednesday, November 10, 2010

Page 121: JavaScript Patterns

mmm duplication...

Wednesday, November 10, 2010

Page 122: JavaScript Patterns

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; } };

Same for all...

Wednesday, November 10, 2010

Page 123: JavaScript Patterns

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; } };

Similar for all..

Wednesday, November 10, 2010

Page 124: JavaScript Patterns

Template Method pattern

Wednesday, November 10, 2010

Page 125: JavaScript Patterns

... and a little bit of Mix-In

Template Method pattern

Wednesday, November 10, 2010

Page 126: JavaScript Patterns

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; }

Extracted same and similar behaviours....

Wednesday, November 10, 2010

Page 127: JavaScript Patterns

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

Augment an action...

Wednesday, November 10, 2010

Page 128: JavaScript Patterns

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

another action...

Wednesday, November 10, 2010

Page 129: JavaScript Patterns

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

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

and last one.

Wednesday, November 10, 2010

Page 130: JavaScript Patterns

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);

and the engine is the same!

Wednesday, November 10, 2010

Page 131: JavaScript Patterns

It’s just a beginning...

Wednesday, November 10, 2010

Page 132: JavaScript Patterns

peep codepeep code

Wednesday, November 10, 2010

Page 133: JavaScript Patterns

Study

Wednesday, November 10, 2010

Page 134: JavaScript Patterns

Wednesday, November 10, 2010

Page 135: JavaScript Patterns

Wednesday, November 10, 2010

Page 136: JavaScript Patterns

“Save it for a rainy day!”

Wednesday, November 10, 2010

Page 137: JavaScript Patterns

Check your code with jslint.com

Wednesday, November 10, 2010

Page 138: JavaScript Patterns

Wednesday, November 10, 2010

Page 139: JavaScript Patterns

@giordanoscalzo

www.slideshare.net/giordano

github.com/gscalzo

[email protected]

Wednesday, November 10, 2010