Skip to content
Browse files

added items to code reuse patterns

  • Loading branch information...
1 parent 60cb81c commit 67ca969bb31d99bc709d271b5ef5d9cc6acb7097 @shichuan shichuan committed Jan 29, 2012
View
76 code-reuse-patterns/borrowing-methods.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html lang="en">
+<head>
+<title>JavaScript Patterns</title>
+<meta charset="utf-8">
+</head>
+<body>
+<script>
+/* Title: Borrowing Methods
+ Description: generally a pattern that should be avoided unless one is more comfortable with class than prototype
+*/
+
+function f() {
+ var args = [].slice.call(arguments, 1, 3);
+ return args;
+}
+
+var one = {
+ name: 'object',
+ say: function (greet) {
+ return greet + ', ' + this.name;
+ }
+};
+
+// test
+console.log(one.say('hi')); // "hi, object"
+
+var two = {
+ name: 'another object'
+};
+
+console.log(one.say.apply(two, ['hello'])); // "hello, another object"
+
+// assigning to a variable
+// `this` will point to the global object
+var say = one.say;
+console.log(say('hoho')); // "hoho, undefined"
+
+// passing as a callback
+var yetanother = {
+ name: "Yet another object",
+ method: function (callback) {
+ return callback('Hola');
+ }
+};
+console.log(yetanother.method(one.say)); // "Holla, undefined"
+
+function bind(o, m) {
+ return function () {
+ return m.apply(o, [].slice.call(arguments));
+ };
+}
+
+var twosay = bind(two, one.say);
+console.log(twosay('yo')); // "yo, another object"
+
+
+if (typeof Function.prototype.bind === 'undefined') {
+ Function.prototype.bind = function (thisArg) {
+ var fn = this,
+ slice = Array.prototype.slice,
+ args = slice.call(arguments, 1);
+ return function () {
+ return fn.apply(thisArg, args.concat(slice.call(arguments)));
+ };
+ };
+}
+
+var twosay2 = one.say.bind(two);
+console.log(twosay2('Bonjour')); // "Bonjour, another object"
+
+var twosay3 = one.say.bind(two, 'Enchanté');
+console.log(twosay3()); // "Enchanté, another object"
+</script>
+</body>
+</html>
View
45 code-reuse-patterns/cp1-default.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<html lang="en">
+<head>
+<title>JavaScript Patterns</title>
+<meta charset="utf-8">
+</head>
+<body>
+<script>
+/* Title: Classical Pattern #1 - The Default Pattern (a pattern that should be generally avoided)
+ Description: create an object using the Parent() constructor and assign this object to the Child()'s prototype
+*/
+
+function inherit(C, P) {
+ C.prototype = new P();
+}
+
+// the parent constructor
+function Parent(name) {
+ this.name = name || 'Adam';
+}
+// adding functionality to the prototype
+Parent.prototype.say = function () {
+ return this.name;
+};
+// empty child constructor
+function Child(name) {}
+
+// inheritance magic happens here
+inherit(Child, Parent);
+
+var kid = new Child();
+console.log(kid.say()); // "Adam"
+
+// Drawback 1: own properties added to `this` is inherited
+var kiddo = new Child();
+kiddo.name = "Patrick";
+console.log(kiddo.say()); // "Patrick"
+
+
+// Drawback 2: it doesn't enable you to pass parameters to the child constructor
+var s = new Child('Seth');
+console.log(s.say()); // "Adam"
+</script>
+</body>
+</html>
View
56 code-reuse-patterns/cp2-rent-a-constructor.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html lang="en">
+<head>
+<title>JavaScript Patterns</title>
+<meta charset="utf-8">
+</head>
+<body>
+<script>
+/* Title: Classical Pattern #2 - Rent a Constructor (a pattern that should be generally avoided)
+ Description: it borrows the parent constructor, passing the child object to be bound to this and also forwarding any arguments
+*/
+
+// the parent constructor
+function Parent(name) {
+ this.name = name || 'Adam';
+}
+
+// adding functionality to the prototype
+Parent.prototype.say = function () {
+ return this.name;
+};
+
+// child constructor
+function Child(name) {
+ Parent.apply(this, arguments);
+}
+
+var kid = new Child("Patrick");
+console.log(kid.name); // "Patrick"
+
+// Drawback 1: nothing from the prototype gets inherited
+console.log(typeof kid.say); // "undefined"
+
+// Multiple Inheritance by Borrowing Constructors
+function Cat() {
+ this.legs = 4;
+ this.say = function () {
+ return "meaowww";
+ }
+}
+
+function Bird() {
+ this.wings = 2;
+ this.fly = true;
+}
+
+function CatWings() {
+ Cat.apply(this);
+ Bird.apply(this);
+}
+
+var jane = new CatWings();
+console.dir(jane);
+</script>
+</body>
+</html>
View
41 code-reuse-patterns/cp3-rent-and-set-prototype.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<html lang="en">
+<head>
+<title>JavaScript Patterns</title>
+<meta charset="utf-8">
+</head>
+<body>
+<script>
+/* Title: Classical Pattern #3 - Rent and Set Prototype (a pattern that should be generally avoided)
+ Description: first borrow the constructor and then also set the child's prototype to point to a new instance of the constructor
+*/
+
+// the parent constructor
+function Parent(name) {
+ this.name = name || 'Adam';
+}
+
+// adding functionality to the prototype
+Parent.prototype.say = function () {
+ return this.name;
+};
+
+// child constructor
+function Child(name) {
+ Parent.apply(this, arguments);
+}
+
+Child.prototype = new Parent();
+
+var kid = new Child("Patrick");
+console.log(kid.name); // "Patrick"
+console.log(typeof kid.say); // function
+console.log(kid.say()); // Patrick
+console.dir(kid);
+delete kid.name;
+console.log(kid.say()); // "Adam"
+
+// Drawback - the parent constructor is called twice, so it could be inefficient
+</script>
+</body>
+</html>
View
40 code-reuse-patterns/cp4-share-the-prototype.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html lang="en">
+<head>
+<title>JavaScript Patterns</title>
+<meta charset="utf-8">
+</head>
+<body>
+<script>
+/* Title: Classical Pattern #3 - Share the Prototype (a pattern that should be generally avoided)
+ Description: first borrow the constructor and then also set the child's prototype to point to a new instance of the constructor
+*/
+
+function inherit(C, P) {
+ C.prototype = P.prototype;
+}
+
+// the parent constructor
+function Parent(name) {
+ this.name = name || 'Adam';
+}
+
+// adding functionality to the prototype
+Parent.prototype.say = function () {
+ return this.name;
+};
+
+// child constructor
+function Child(name) {}
+
+inherit(Child, Parent);
+
+var kid = new Child('Patrick');
+console.log(kid.name); // undefined
+console.log(typeof kid.say); // function
+kid.name = 'Patrick';
+console.log(kid.say()); // Patrick
+console.dir(kid);
+</script>
+</body>
+</html>
View
72 code-reuse-patterns/cp5-a-temporary-constructor.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<html lang="en">
+<head>
+<title>JavaScript Patterns</title>
+<meta charset="utf-8">
+</head>
+<body>
+<script>
+/* Title: Classical Pattern #5 - A Temporary Constructor (a pattern that should be generally avoided)
+ Description: first borrow the constructor and then also set the child's prototype to point to a new instance of the constructor
+*/
+
+/* Basic */
+/*function inherit(C, P) {
+ var F = function () {};
+ F.prototype = P.prototype;
+ C.prototype = new F();
+}*/
+
+/* Storing the Superclass */
+/*function inherit(C, P) {
+ var F = function () {};
+ F.prototype = P.prototype;
+ C.prototype = new F();
+ C.uber = P.prototype;
+}*/
+
+/* Resetting the Constructor Pointer */
+/*function inherit(C, P) {
+ var F = function () {};
+ F.prototype = P.prototype;
+ C.prototype = new F();
+ C.uber = P.prototype;
+ C.prototype.constructor = C;
+}*/
+
+/* in closure */
+var inherit = (function () {
+ var F = function () {};
+ return function (C, P) {
+ F.prototype = P.prototype;
+ C.prototype = new F();
+ C.uber = P.prototype;
+ C.prototype.constructor = C;
+ }
+}());
+
+function Parent(name) {
+ this.name = name || 'Adam';
+}
+
+// adding functionality to the prototype
+Parent.prototype.say = function () {
+ return this.name;
+};
+
+// child constructor
+function Child(name) {}
+
+inherit(Child, Parent);
+
+var kid = new Child();
+console.log(kid.name); // undefined
+console.log(typeof kid.say); // function
+kid.name = 'Patrick';
+console.log(kid.say()); // Patrick
+console.log(kid.constructor.name); // Child
+console.log(kid.constructor === Parent); // false
+
+</script>
+</body>
+</html>
View
74 code-reuse-patterns/inheritance-by-copying-properties.html
@@ -0,0 +1,74 @@
+<!doctype html>
+<html lang="en">
+<head>
+<title>JavaScript Patterns</title>
+<meta charset="utf-8">
+</head>
+<body>
+<script>
+/* Title: Inheritance by Copying Properties
+ Description: an object gets functionality from another object, simply by copying it
+*/
+
+/* shallow copy */
+function extend(parent, child) {
+ var i;
+ child = child || {};
+ for (i in parent) {
+ if (parent.hasOwnProperty(i)) {
+ child[i] = parent[i];
+ }
+ }
+ return child;
+}
+
+var dad = {name: "Adam"};
+var kid = extend(dad);
+console.log(kid.name); // "Adam"
+
+var dad = {
+ counts: [1, 2, 3],
+ reads: {paper: true}
+};
+var kid = extend(dad);
+kid.counts.push(4);
+console.log(dad.counts.toString()); // "1,2,3,4"
+console.log(dad.reads === kid.reads); // true
+
+
+/* deep copy */
+function extendDeep(parent, child) {
+ var i,
+ toStr = Object.prototype.toString,
+ astr = "[object Array]";
+
+ child = child || {};
+
+ for (i in parent) {
+ if (parent.hasOwnProperty(i)) {
+ if (typeof parent[i] === 'object') {
+ child[i] = (toStr.call(parent[i]) === astr) ? [] : {};
+ extendDeep(parent[i], child[i]);
+ } else {
+ child[i] = parent[i];
+ }
+ }
+ }
+ return child;
+}
+
+var dad = {
+ counts: [1, 2, 3],
+ reads: {paper: true}
+};
+var kid = extendDeep(dad);
+
+kid.counts.push(4);
+console.log(kid.counts.toString()); // "1,2,3,4"
+console.log(dad.counts.toString()); // "1,2,3"
+
+console.log(dad.reads === kid.reads); // false
+kid.reads.paper = false;
+</script>
+</body>
+</html>
View
6 code-reuse-patterns/klass.html
@@ -6,10 +6,14 @@
</head>
<body>
<script>
-/* Title: Klass
+/* Title: Klass (a pattern that should be generally avoided)
Description: generally a pattern that should be avoided unless one is more comfortable with class than prototype
*/
+// Drawback: it brings the whole confusing notion of classes, which don’t technically exist in the language
+
+// Benefit: you can tweak the syntax and the conventions to resemble another of your favorite languages
+
var klass = function (Parent, props) {
var Child, F, i;
View
35 code-reuse-patterns/mix-ins.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<html lang="en">
+<head>
+<title>JavaScript Patterns</title>
+<meta charset="utf-8">
+</head>
+<body>
+<script>
+/* Title: Mix-ins
+ Description: generally a pattern that should be avoided unless one is more comfortable with class than prototype
+*/
+
+function mix() {
+ var arg, prop, child = {};
+ for (arg = 0; arg < arguments.length; arg += 1) {
+ for (prop in arguments[arg]) {
+ if (arguments[arg].hasOwnProperty(prop)) {
+ child[prop] = arguments[arg][prop];
+ }
+ }
+ }
+ return child;
+}
+
+var cake = mix(
+ {eggs: 2, large: true},
+ {butter: 1, salted: true},
+ {flour: "3 cups"},
+ {sugar: "sure!"}
+);
+
+console.dir(cake);
+</script>
+</body>
+</html>
View
73 code-reuse-patterns/prototypal-inheritance.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<html lang="en">
+<head>
+<title>JavaScript Patterns</title>
+<meta charset="utf-8">
+</head>
+<body>
+<script>
+/* Title: Prototypal Inheritance
+ Description: objects inherit from other objects
+*/
+
+function object(o) {
+ function F() {}
+ F.prototype = o;
+ return new F();
+}
+
+// object to inherit from
+var parent = {
+ name: "Papa"
+};
+
+// the new object
+var child = object(parent);
+
+// testing
+alert(child.name); // "Papa"
+
+
+// parent constructor
+function Person() {
+ // an "own" property
+ this.name = "Adam";
+}
+// a property added to the prototype
+Person.prototype.getName = function () {
+ return this.name;
+};
+// create a new person
+var papa = new Person();
+// inherit
+var kid = object(papa);
+// test that both the own property
+// and the prototype property were inherited
+kid.getName(); // "Adam"
+
+
+// parent constructor
+function Person() {
+ // an "own" property
+ this.name = "Adam";
+}
+// a property added to the prototype
+Person.prototype.getName = function () {
+ return this.name;
+};
+// inherit
+var kid = object(Person.prototype);
+typeof kid.getName; // "function", because it was in the prototype
+typeof kid.name; // "undefined", because only the prototype was inherited
+
+
+/* Addition to ECMAScript 5 */
+var child = Object.create(parent);
+
+var child = Object.create(parent, {
+age: { value: 2 } // ECMA5 descriptor
+});
+child.hasOwnProperty("age"); // true
+</script>
+</body>
+</html>

0 comments on commit 67ca969

Please sign in to comment.
Something went wrong with that request. Please try again.