Last active
January 25, 2016 18:12
-
-
Save dd3141592/fa4e86b8c97a34890df8 to your computer and use it in GitHub Desktop.
crib notes and some examples from "JavaScript Patterns" by Stoyan Stefanov //Chapter 5 Object Creation Patterns
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="CH 5 Object Creation Patterns" content="Javascript Patterns"> | |
<meta charset="utf-8"> | |
<title>JS Bin</title> | |
</headJavascript patterns | |
<body> | |
Javascript Patterns, by Stoyan Stefanov (O'Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750. | |
<script id="jsbin-javascript"> | |
//My crib notes from "JavaScript Patterns" by Stoyan Stefanov | |
//Chapter 5 Object Creation Patterns | |
//includes some examples too | |
//you will need to buy the book - these notes are sketchy and for review & reference only | |
"use strict"; | |
//Namespace pattern | |
//namespacing function | |
// if a namespace exists it won't be recreated | |
// will return a reference to a module to a local var | |
// will handle long namespaces | |
//example | |
var myApp = myApp || {}; | |
myApp.namespace = function(name){ | |
var names = name.split("."), | |
parent = myApp; | |
if(names[0] === "myApp"){ | |
names = names.slice(1); | |
} | |
var len = names.length; | |
for(var i = 0; i < len; i++){ | |
if(typeof parent[names[i]] === "undefined") { | |
parent[names[i]] = {}; | |
} | |
parent = parent[names[i]]; | |
} | |
return parent; | |
}; | |
//Declaring dependencies | |
//benefits include -easy, faster, clearer, minification - will now minify name modules | |
//example | |
function test(){ | |
var modules = myApp.modules; | |
} | |
//Private properties and methods | |
//example - create a private property with a constructor | |
// and a public accessor method for the property | |
var myObj = (function example(){ | |
var name = "mr. big"; | |
return{ | |
getName : function(){ return name;} | |
}; | |
})(); | |
console.log(myObj.getName()); | |
//beware returning reference to private object | |
//example | |
var myObj = (function example(){ | |
var name = { salutation: "mr. big", | |
firstName: "bill", | |
lastName: "big"} ; | |
return{ | |
getName : function(){ return name;} | |
}; | |
})(); | |
console.log(myObj.getName().firstName); | |
//use POLA (principle of least authority) to take care of this loophole | |
var myObj1 = (function example(){ | |
var name = { salutation: "mr. big", | |
firstName: "bill", | |
lastName: "big"} ; | |
return{ | |
getName : function(){ | |
return { | |
lastName: name.lastName, | |
salutation: name.salutation | |
}; | |
}}; | |
})(); | |
console.log(myObj1.getName().salutation); | |
console.log(myObj1.getName().firstName); | |
//Or | |
var myObj2 = (function example(){ | |
var name = { salutation: "mr. big", | |
firstName: "bill", | |
lastName: "big"} ; | |
return{ | |
getSalutation : function(){ | |
return name.salutation; | |
}, | |
getlastName : function(){ | |
return name.lastName; | |
} | |
}; | |
})(); | |
console.log(myObj2.getSalutation()); | |
console.log(myObj2.getlastName()); | |
//prototypes and privacy | |
//private members in constructors and also object literals | |
//common parts to prototype property of constructor | |
//example: | |
function Gadget(str){ | |
//private member | |
var name = str; | |
//public function | |
if(!( this instanceof Gadget)){ | |
console.log("oh oh"); | |
return new Gadget(str); | |
} | |
this.getName = function(){ | |
return name; | |
}; | |
} | |
Gadget.prototype = (function(){ | |
//private member | |
var browser = "mobile webkit"; | |
//public prototype members | |
return { | |
getBrowser: function(){ | |
return browser; | |
} | |
}; | |
})(); | |
var toy = new Gadget("ipod"); | |
console.log(toy.getName()); | |
console.log(toy.getBrowser()); | |
var phone = new Gadget("iphone 6"); | |
console.log(phone.getName()); | |
console.log(phone.getBrowser()); | |
//question - what happens if we forget the new keyword? | |
var badtoy = Gadget("drone"); | |
console.log(badtoy.getName()); | |
console.log(badtoy.getBrowser()); | |
//revealing private functions as public methods | |
var myObj = (function (){ | |
var temp = 1, | |
logMe = function(str){ | |
console.log(str); | |
}; | |
return { | |
logMe : logMe | |
}; | |
})(); | |
myObj.logMe("this is revelation pattern"); | |
//module pattern | |
//use namespace function and revelation pattern | |
myApp.namespace("myApp.utilities.array"); | |
myApp.utilities.array = (function (){ | |
var temp = 1, | |
logMe = function(str){ | |
console.log(str); | |
}; | |
return { | |
logMe : logMe | |
}; | |
})(); | |
myApp.utilities.array.logMe("this is the revealing module pattern"); | |
//Sandbox pattern | |
//avoid global like myApp, long namespace names etc. | |
//one global contructor function only | |
// use this to construct objects and returns a callback | |
//Global constructor | |
//example | |
//new Sandbox(box); | |
//where box is like the myApp object - has all the functionality to make | |
//code work | |
//use the new pattern - so we can eliminate it | |
//also pass in a configuration object with all the required modules etc. | |
//example - | |
//Sandbox(['ajax', 'event'], function(box){}); | |
//example - if we omit module names assume use all modules | |
//Sandbox(function(box){}); | |
// can keep global namespace clear; can call Sandbox multiple times with | |
// different box objects | |
//adding modules & | |
//implementing the constructor | |
// example | |
//Sandbox.modules = {}; | |
//Sandbox.modules.dom = function(box){ box.getElement = function(){}; | |
// box.getStyle = function(){}; box.foo = "bar"; | |
//}; etc... | |
// implementation | |
//example | |
// function Sandbox(){ | |
// var array = Array.prototype.slice.call(arguments), | |
// callback = array.pop(); | |
// modules = ( array[0] && (typeof array[0] === "string")) ? | |
// array : array[0], | |
// i; | |
// if(!(this instanceof Sandbox){ | |
// return new Sandox(modules,callback); | |
// } | |
// check to see if no modules specified or "*" - means use all | |
// in this case add all modules to this object | |
// if(!modules || modules === "*"){ | |
// modules = []; | |
// for(i in Sandbox.modules){ | |
// if(Sandbox.modules.hasOwnProperty[i]) | |
// modules.push(i); | |
//} | |
//} | |
// initialize modules | |
// for(i = 0 ; i < modules.length; i++){ //Sandbox.modules[module[i]](this); } | |
// call the call back | |
// callback(this); | |
//} | |
// add any prototype properties as needed | |
// example | |
// Sandbox.prototype = { name: "", version: 2, getName: function(){return this.name}}; | |
//static members - i.e.available to all instances and called by the | |
// object name | |
//example of public static methods | |
var Gadget = function(){ | |
}; | |
// public static method | |
Gadget.isCool = function(){ | |
console.log("yes!"); | |
}; | |
//public prototype method | |
Gadget.prototype.setPrice = function(price){ | |
this.price = price; | |
}; | |
var iphone = new Gadget(); | |
Gadget.isCool(); | |
//can't call with instance | |
//iphone.isCool(); | |
//to have static work with instance too | |
Gadget.prototype.isCool = Gadget.isCool; | |
iphone.isCool(); | |
//work differently if called by instance vs statically | |
var Gadget = function (price){ | |
this.price = price; | |
}; | |
Gadget.isCool = function(){ | |
if(this instanceof Gadget){ | |
console.log("yes! and it's price is:" + this.price ); | |
} else { | |
console.log("yes!"); | |
} | |
}; | |
Gadget.prototype.isCool = Gadget.isCool; | |
var iphone6 = new Gadget(700); | |
Gadget.isCool(); | |
iphone6.isCool(); | |
//private static methods | |
var Gadget = (function(){ | |
var count = 0; | |
return function(){ | |
count++; | |
console.log(count); | |
} | |
})(); | |
var g = new Gadget(); | |
var h = new Gadget() | |
//create a privileged method to return the static private property | |
// like getMyId() | |
var Gadget = (function(){ | |
var count = 0, | |
newGadget; | |
newGadget = function(){ | |
count++; | |
this.countId = count; | |
}; | |
newGadget.prototype.getMyId = function(){ | |
return "my id: " + this.countId + " out of " + count; | |
}; | |
return newGadget; | |
})(); | |
var g1 = new Gadget(); | |
var h1 = new Gadget() | |
console.log(h1.getMyId()); | |
console.log(g1.getMyId()); | |
//Object constants | |
</script> | |
<script id="jsbin-source-javascript" type="text/javascript">//My crib notes from "JavaScript Patterns" by Stoyan Stefanov | |
//Chapter 5 Object Creation Patterns | |
//includes some examples too | |
//you will need to buy the book - these notes are sketchy and for review & reference only | |
"use strict"; | |
//Namespace pattern | |
//namespacing function | |
// if a namespace exists it won't be recreated | |
// will return a reference to a module to a local var | |
// will handle long namespaces | |
//example | |
var myApp = myApp || {}; | |
myApp.namespace = function(name){ | |
var names = name.split("."), | |
parent = myApp; | |
if(names[0] === "myApp"){ | |
names = names.slice(1); | |
} | |
var len = names.length; | |
for(var i = 0; i < len; i++){ | |
if(typeof parent[names[i]] === "undefined") { | |
parent[names[i]] = {}; | |
} | |
parent = parent[names[i]]; | |
} | |
return parent; | |
}; | |
//Declaring dependencies | |
//benefits include -easy, faster, clearer, minification - will now minify name modules | |
//example | |
function test(){ | |
var modules = myApp.modules; | |
} | |
//Private properties and methods | |
//example - create a private property with a constructor | |
// and a public accessor method for the property | |
var myObj = (function example(){ | |
var name = "mr. big"; | |
return{ | |
getName : function(){ return name;} | |
}; | |
})(); | |
console.log(myObj.getName()); | |
//beware returning reference to private object | |
//example | |
var myObj = (function example(){ | |
var name = { salutation: "mr. big", | |
firstName: "bill", | |
lastName: "big"} ; | |
return{ | |
getName : function(){ return name;} | |
}; | |
})(); | |
console.log(myObj.getName().firstName); | |
//use POLA (principle of least authority) to take care of this loophole | |
var myObj1 = (function example(){ | |
var name = { salutation: "mr. big", | |
firstName: "bill", | |
lastName: "big"} ; | |
return{ | |
getName : function(){ | |
return { | |
lastName: name.lastName, | |
salutation: name.salutation | |
}; | |
}}; | |
})(); | |
console.log(myObj1.getName().salutation); | |
console.log(myObj1.getName().firstName); | |
//Or | |
var myObj2 = (function example(){ | |
var name = { salutation: "mr. big", | |
firstName: "bill", | |
lastName: "big"} ; | |
return{ | |
getSalutation : function(){ | |
return name.salutation; | |
}, | |
getlastName : function(){ | |
return name.lastName; | |
} | |
}; | |
})(); | |
console.log(myObj2.getSalutation()); | |
console.log(myObj2.getlastName()); | |
//prototypes and privacy | |
//private members in constructors and also object literals | |
//common parts to prototype property of constructor | |
//example: | |
function Gadget(str){ | |
//private member | |
var name = str; | |
//public function | |
if(!( this instanceof Gadget)){ | |
console.log("oh oh"); | |
return new Gadget(str); | |
} | |
this.getName = function(){ | |
return name; | |
}; | |
} | |
Gadget.prototype = (function(){ | |
//private member | |
var browser = "mobile webkit"; | |
//public prototype members | |
return { | |
getBrowser: function(){ | |
return browser; | |
} | |
}; | |
})(); | |
var toy = new Gadget("ipod"); | |
console.log(toy.getName()); | |
console.log(toy.getBrowser()); | |
var phone = new Gadget("iphone 6"); | |
console.log(phone.getName()); | |
console.log(phone.getBrowser()); | |
//question - what happens if we forget the new keyword? | |
var badtoy = Gadget("drone"); | |
console.log(badtoy.getName()); | |
console.log(badtoy.getBrowser()); | |
//revealing private functions as public methods | |
var myObj = (function (){ | |
var temp = 1, | |
logMe = function(str){ | |
console.log(str); | |
}; | |
return { | |
logMe : logMe | |
}; | |
})(); | |
myObj.logMe("this is revelation pattern"); | |
//module pattern | |
//use namespace function and revelation pattern | |
myApp.namespace("myApp.utilities.array"); | |
myApp.utilities.array = (function (){ | |
var temp = 1, | |
logMe = function(str){ | |
console.log(str); | |
}; | |
return { | |
logMe : logMe | |
}; | |
})(); | |
myApp.utilities.array.logMe("this is the revealing module pattern"); | |
//Sandbox pattern | |
//avoid global like myApp, long namespace names etc. | |
//one global contructor function only | |
// use this to construct objects and returns a callback | |
//Global constructor | |
//example | |
//new Sandbox(box); | |
//where box is like the myApp object - has all the functionality to make | |
//code work | |
//use the new pattern - so we can eliminate it | |
//also pass in a configuration object with all the required modules etc. | |
//example - | |
//Sandbox(['ajax', 'event'], function(box){}); | |
//example - if we omit module names assume use all modules | |
//Sandbox(function(box){}); | |
// can keep global namespace clear; can call Sandbox multiple times with | |
// different box objects | |
//adding modules & | |
//implementing the constructor | |
// example | |
//Sandbox.modules = {}; | |
//Sandbox.modules.dom = function(box){ box.getElement = function(){}; | |
// box.getStyle = function(){}; box.foo = "bar"; | |
//}; etc... | |
// implementation | |
//example | |
// function Sandbox(){ | |
// var array = Array.prototype.slice.call(arguments), | |
// callback = array.pop(); | |
// modules = ( array[0] && (typeof array[0] === "string")) ? | |
// array : array[0], | |
// i; | |
// if(!(this instanceof Sandbox){ | |
// return new Sandox(modules,callback); | |
// } | |
// check to see if no modules specified or "*" - means use all | |
// in this case add all modules to this object | |
// if(!modules || modules === "*"){ | |
// modules = []; | |
// for(i in Sandbox.modules){ | |
// if(Sandbox.modules.hasOwnProperty[i]) | |
// modules.push(i); | |
//} | |
//} | |
// initialize modules | |
// for(i = 0 ; i < modules.length; i++){ //Sandbox.modules[module[i]](this); } | |
// call the call back | |
// callback(this); | |
//} | |
// add any prototype properties as needed | |
// example | |
// Sandbox.prototype = { name: "", version: 2, getName: function(){return this.name}}; | |
//static members - i.e.available to all instances and called by the | |
// object name | |
//example of public static methods | |
var Gadget = function(){ | |
}; | |
// public static method | |
Gadget.isCool = function(){ | |
console.log("yes!"); | |
}; | |
//public prototype method | |
Gadget.prototype.setPrice = function(price){ | |
this.price = price; | |
}; | |
var iphone = new Gadget(); | |
Gadget.isCool(); | |
//can't call with instance | |
//iphone.isCool(); | |
//to have static work with instance too | |
Gadget.prototype.isCool = Gadget.isCool; | |
iphone.isCool(); | |
//work differently if called by instance vs statically | |
var Gadget = function (price){ | |
this.price = price; | |
}; | |
Gadget.isCool = function(){ | |
if(this instanceof Gadget){ | |
console.log("yes! and it's price is:" + this.price ); | |
} else { | |
console.log("yes!"); | |
} | |
}; | |
Gadget.prototype.isCool = Gadget.isCool; | |
var iphone6 = new Gadget(700); | |
Gadget.isCool(); | |
iphone6.isCool(); | |
//private static methods | |
var Gadget = (function(){ | |
var count = 0; | |
return function(){ | |
count++; | |
console.log(count); | |
} | |
})(); | |
var g = new Gadget(); | |
var h = new Gadget() | |
//create a privileged method to return the static private property | |
// like getMyId() | |
var Gadget = (function(){ | |
var count = 0, | |
newGadget; | |
newGadget = function(){ | |
count++; | |
this.countId = count; | |
}; | |
newGadget.prototype.getMyId = function(){ | |
return "my id: " + this.countId + " out of " + count; | |
}; | |
return newGadget; | |
})(); | |
var g1 = new Gadget(); | |
var h1 = new Gadget() | |
console.log(h1.getMyId()); | |
console.log(g1.getMyId()); | |
//Object constants | |
</script></body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment