Code Reuse And Design Patterns




Navigate with keyboard arrows in all directions.
Use the control on the bottom right part as page availability hint.

Code Reuse Patterns

Prototypal Inheritance



With prototypal inheritance we reuse code (attributes and methods).
This is done with creation of objects based on already created objects.

We need something like:

item = createLike(model);


Before seeing how 'createLike' method looks like lets see some theory...

In JavaScript everything is object

...but this sometimes is confusing


  • We have a root Object
  • We create Objects using Objects
  • We create Objects based on other Objects


Shall we classify these objects somehow? See next...

We have three kinds of objects

The 'triplet'


  1. Data Holder

  2. Model

  3. Creator



Lets give some explanation...

Relations inside the triplet

Data Holder Object

Definition: Object that holds data. All objects are Data Holders.


The simplest way to create DataHolder object is with object literal

var address = {
	street: "Sunset",
	number: 5
}
assertEquals("Sunset", address.street);
assertEquals(5, address.number);
						

At some point in time we could decide to turn 'address' Data Holder object into a Model object. See the Model object definition next...

Model Object

Definition: Object used as a model for creating Data Holder objects

var address = {
	street: "Sunset",
	number: 5
}
assertEquals("Sunset", address.street);
assertEquals(5, address.number);
						

Our address object could become a model for creation of more objects e.g. kind of extended addresses. Two questions arise...

How to define Creator object?

How to tell him to create objects using 'address' as a model?

Creator Object

Definition: Object that can create Data Holder objects based on a Model object


In JavaScript Function Objects are Creator Objects

//Define Creator Object							
function ExtendedAddress () {
	this.zipCode = 555;
};
//Create Data Holder Object
var extendedAddress = new ExtendedAddress(); 
assertEquals(555, extendedAddress.zipCode);
						

How to define Creator object? -> With JavaScript constructor function

How to tell him to create objects using address as a model? See next...

Instructing Creator objects what models to use

In JavaScript we can use the "prototype" property


var address = {
	street: "Sunset",
	number: 5
};
function ExtendedAddress () {
	this.zipCode = 555;
}

//Here we define the Model that this Creator will use
ExtendedAddress.prototype = address; 

var extAddress = new ExtendedAddress(); 
assertEquals(555, extAddress.zipCode);
assertEquals("Sunset", extAddress.street);
assertEquals(5, extAddress.number);
						

The default model

we were able to create objects before setting the Model

//Define Creator Object							
function ExtendedAddress () {
	this.zipCode = 555;
};
//Create Data Holder Object
var extendedAddress = new ExtendedAddress(); 
assertEquals(555, extendedAddress.zipCode);
						

What is the default Model that ExtendedAddress is using? Answer: JavaScript automatically creates object with the same name (ExtendedAddress) and use it as a Model (assign it to Creator Object 'prototype' property)

Don't confuse the Creator and the Model. Have in mind that:

assertFalse(ExtendedAddress === ExtendedAddress.prototype)

Code for tracking the existence of the triplet

function CreatorObject(label){
	this.label = label || "DefaultDataHolderLabel";
}
var creatorObject = CreatorObject;
creatorObject.label = "creatorObjectLabel";

var modelObject = CreatorObject.prototype;
modelObject.label = "modelObjectLabel";

var dataHolderObject1 = new CreatorObject();
var dataHolderObject2 = new CreatorObject("ConcreteDataHolderLabel");

assertEquals(modelObject.label, "modelObjectLabel");
assertEquals(creatorObject.label, "creatorObjectLabel");
assertEquals(dataHolderObject1.label, "DefaultDataHolderLabel");
assertEquals(dataHolderObject2.label, "ConcreteDataHolderLabel");
						

The Triplet Cheat Sheet

THE PROTOTYPAL INHERITANCE IMPLEMENTATION

Here is how 'createLike' method looks like

function createLike(o) {
	//Define Creator Object
        function F() {}  
        
        //Set the Model Object
        F.prototype = o; 
        
        //Create Data Holder based on the Model
        return new F();
};
    					

DISCUSSION

What exactly is inherited?

  • Data Holder Object is kind of a data set
  • It owns data defined during its creation with Creator Object
  • It inherites 'live' data defined in its Model Object


See example on the next slide...

DISCUSSION

Example of own and inherited data

var address = {street: "Sunset", number: 5};
function ExtendedAddress () {this.zipCode = 555;}

//Here we define the Model that this Creator will use
ExtendedAddress.prototype = address; 

var extAddress = new ExtendedAddress(); 
assertEquals(555, extAddress.zipCode);
assertEquals("Sunset", extAddress.street);
assertEquals(5, extAddress.number);

//Add own data
extAddress.newOwnProp = 1;

//Add more data into Model and it will be visible
address.newInheritedProp = 2;
assertEquals(1, extAddress.newOwnProp);
assertEquals(2, extAddress.newInheritedProp);
    					

DISCUSSION

Where are the roots of all this?

  • The first Model Object is the JavaScript built-in Object{} object
  • It is accessible with Object.prototype
  • It is the first because it has no Model: Object.prototype.__proto__ = null
  • Its Creator Object is Object() constructor function:
    Object.prototype.constructor = Object()

DISCUSSION

Where are the roots of all this?

  • The second Model Object is the JavaScript built-in Function object
  • It is accessible with Function.prototype
  • It is created using built-in Object{} as a Model:
    Function.prototype.__proto__ = Object{}
  • Its Creator Object is Function() constructor function:
    Function.prototype.constructor = Function()

DISCUSSION

Where are the roots of all this?

  • Now if you create new Data Holder object:
    var dataHolder = new Object();
    Its model will be built-in Object{}: dataHolder.__proto__ = Object{}
  • If you create new Creator object: function Creator() {}
    Its Model will be built-in Function object: Creator.__proto__ = Function{}

    (...and Function{} is modeled by Object{}
    so we are saying that functions are objects in JavaScript)

Code Reuse Patterns

Classical Inheritance



JavaScript Patterns Book

Pro JavaScript Design Patterns Book

Design Patterns

References



JavaScript Patterns Book

Pro JavaScript Design Patterns Book

Essential JavaScript Design Patterns by Addy Osmani

Collection Of Design Patterns