*at least some of them...
Elements of reusable object-oriented software which describe simple and elegant solutions to specific problems in object-oriented software design.
var Car = function(model, year, miles) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function() {
return this.model + ' has done ' + this.miles + ' miles';
};
}
// Usage:
// We can create new instances of the car
var civic = new Car('Honda Civic', 2009, 20000);
var mondeo = new Car('Ford Mondeo', 2010, 5000);
// and then open our browser console to view the
// output of the toString() method being called on
// these objects
console.log(civic.toString()); // "Honda Civic has done 20000 miles"
console.log(mondeo.toString()); // "Ford Mondeo has done 5000 miles"
var Car = function(model, year, miles) {
this.model = model;
this.year = year;
this.miles = miles;
}
// Note here that we are using Object.prototype.newMethod rather than
// Object.prototype so as to avoid redefining the prototype object
Car.prototype.toString = function() {
return this.model + ' has done ' + this.miles + ' miles';
};
// Usage:
var civic = new Car('Honda Civic', 2009, 20000);
var mondeo = new Car('Ford Mondeo', 2010, 5000);
console.log(civic.toString()); // "Honda Civic has done 20000 miles"
console.log(mondeo.toString()); // "Ford Mondeo has done 5000 miles"
var myModule = (function() {
var myPrivateVar, myPrivateMethod;
// A private variable
myPrivateVar = 0;
// A private function which logs any arguments
myPrivateMethod = function(foo) {
console.log(foo);
};
return {
// A public variable
myPublicVar: "foo",
// A public function utilizing privates
myPublicFunction: function(bar) {
// Do smth with our private variable
myPrivateVar++;
// Call our private method using bar
myPrivateMethod(bar);
}
};
})();
var counter = (function() {
var value = 0;
return {
increment: function() {
return value++;
},
reset: function() {
console.log("counter value prior to reset: " + value);
value = 0;
}
};
})();
// Usage:
// Increment our counter
console.log(counter.increment()); // 0
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
// Reset the counter value
counter.reset(); // 3
// Increment our counter
console.log(counter.increment()); // 0
console.log(counter.increment()); // 1
var $ = 'another cool framework';
// Global module
var myModule = (function($) {
function privateMethod1() {
$(".container").html("Hello World!");
}
function privateMethod2() {
console.log('called private method');
}
return {
publicMethod: function() {
privateMethod1();
// other stuff
}
};
// Pull in jQuery
})(jQuery);
myModule.publicMethod();
var myModule = (function(exports) {
var module1 = exports.module1;
var module2 = exports.module2;
var privateMethod = function() {
console.log('called private method');
module1.doSomeStuff();
module2.doSomeStuff();
}
return {
publicMethod: function() {
privateMethod();
// other stuff
}
};
// Pull in dependencies
})(exports);
myModule.publicMethod();
// somewhere in other file
var exports = {
module1: { /* public api goes here */ },
module2: { /* public api goes here */ }
};
var myRevealingModule = (function () {
var privateVar = 'Ben Cherry';
var publicVar = 'Hey there!';
var privateFunction = function() {
console.log('Name: ' + privateVar);
}
var publicSetName = function(strName) {
privateVar = strName;
}
var publicGetName = function() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName('Paul Kinlan');
var singleton = (function() {
// Instance stores a reference to the Singleton
var instance;
var init = function() {
// Private methods and variables
var randomString = 'I\'m random, believe me!';
return {
getRandomString: function() {
return randomString;
}
};
};
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
};
})();
console.log(singleton.getInstance().getRandomString()); // random string
console.log(singleton.getInstance() === singleton.getInstance()); // true
var ObserverList = function() {
this.observerList = [];
}
$.extend(ObserverList.prototype, {
add: function(obj) {
return this.observerList.push(obj);
},
count: function() {
return this.observerList.length;
},
get: function(index) {
return this.observerList[index];
},
indexOf: function(obj, startIndex) {
var i = startIndex || 0;
while (i < this.observerList.length) {
if (this.observerList[i] === obj) {
return i;
}
i++;
}
return -1;
},
removeAt: function(index) {
this.observerList.splice(index, 1);
}
});
var Subject = function() {
this.observers = new ObserverList();
}
$.extend(Subject.prototype, {
addObserver: function(observer) {
this.observers.add(observer);
},
removeObserver: function(observer) {
this.observers.removeAt(this.observers.indexOf(observer, 0));
},
notifyPropertyChanged: function(propertyName) {
var observerCount = this.observers.count(), i;
for (i = 0; i < observerCount; i++) {
debugger;
this.observers.get(i).onSubjectPropertyChanged(this, propertyName);
}
}
});
var Observer = function() {
this.onSubjectPropertyChanged = function(subject, propertyName) {};
};
var subjectCheckbox = document.getElementById('subjectCheckbox');
var addObserverButton = document.getElementById('addNewObserver');
var observersContainer = document.getElementById('observersContainer');
$.extend(subjectCheckbox, new Subject());
subjectCheckbox.onclick = function() {
this.notifyPropertyChanged('checked');
};
addObserverButton.onclick = function() {
var observerCheckbox = document.createElement('input');
observerCheckbox.type = 'checkbox';
$.extend(observerCheckbox, new Observer());
observerCheckbox.onSubjectPropertyChanged = function(subject, propertyName) {
debugger;
if (propertyName === 'checked') {
this.checked = subject[propertyName];
}
}
subjectCheckbox.addObserver(observerCheckbox);
observersContainer.appendChild(observerCheckbox);
};
<button id="addNewObserver">Add New Observer checkbox</button>
<input id="subjectCheckbox" type="checkbox"/>
<div id="observersContainer"></div>
var pubsub = $('div');
<button id="addNewSubscriber">Add New Subscriber checkbox</button>
<input id="publisherCheckbox1" type="checkbox"/>
<input id="publisherCheckbox2" type="checkbox"/>
<div id="subscribersContainer"></div>
var pubsub = $('div');
var publisherCheckbox1 = document.getElementById('publisherCheckbox1');
var publisherCheckbox2 = document.getElementById('publisherCheckbox2');
var addSubscriberButton = document.getElementById('addNewSubscriber');
var subscribersContainer = document.getElementById('subscribersContainer');
var publisherClickHandler = function () {
if (this.checked) {
pubsub.trigger('checked');
} else {
pubsub.trigger('unchecked');
}
};
publisherCheckbox1.onclick = publisherClickHandler;
publisherCheckbox2.onclick = publisherClickHandler;
addSubscriberButton.onclick = function() {
var subscriberCheckbox = document.createElement('input');
subscriberCheckbox.type = 'checkbox';
pubsub.on('checked', function () {
subscriberCheckbox.checked = true;
});
pubsub.on('unchecked', function () {
subscriberCheckbox.checked = false;
});
subscribersContainer.appendChild(subscriberCheckbox);
};
var orgChart = {
addNewEmployee: function(){
// getEmployeeDetail provides a view that users interact with
var employeeDetail = this.getEmployeeDetail();
// when the employee detail is complete, the mediator (the 'orgchart' object)
// decides what should happen next
employeeDetail.on("complete", function(employee){
// set up additional objects that have additional events, which are used
// by the mediator to do additional things
var managerSelector = this.selectManager(employee);
managerSelector.on("save", function(employee){
employee.save();
});
});
},
// ...
}
var Command = function(target, methodName, var_args) {
// get target method and validate it
var method = target && target[methodName];
if (!method || typeof method !== 'function') {
throw 'Target object should contain method: "' + methodName + '"';
}
this.target = target;
this.method = method;
// check any predefined args
if (var_args) {
this.args = [].splice.call(arguments, 2);
} else {
this.args = [];
}
};
Command.prototype.execute = function() {
return this.method.apply(this.target, this.args);
}
var diceRollView = (function() {
var diceElement = document.getElementById('dice');
return {
generateNumber: function(from, to) {
diceElement.innerText = Math.round(Math.random() * (to - from) + from);
}
}
}());
// encapsulate dice roll login in a single command and pass it to the view
var rollTheDiceCommand = new Command(diceRollView, 'generateNumber', 1, 6);
var userInteractionView = (function(rollCommand) {
var rollButton = document.getElementById('roll');
return {
init: function() {
rollButton.onclick = function() {
rollCommand.execute();
}
}
}
}(rollTheDiceCommand));
userInteractionView.init();
<button id="roll">Roll the dice!</button>
<div id="dice"></div>
var addEvent = function(element, eventName, handler) {
if (element.addEventListener) {
element.addEventListener(eventName, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + eventName, handler);
} else {
element["on" + eventName] = handler;
}
};
var WebSocketTransport = function () {
// websocket implementation details
};
var AjaxTransport = function () {
// long polling/polling implementation details
};
var StubbedTransport = function () {
// some test data implementation
};
var environment = 'test';
var realtimeTransportFactory = (function () {
return {
createTransport: function (options) {
if (environment === 'test') {
return new StubbedTransport(options);
} else if (window.WebSocket) {
return new WebSocketTransport(options);
} else {
return new AjaxTransport(options);
}
}
};
}());
var transport = realtimeTransportFactory.createTransport();
console.log(transport instanceof StubbedTransport); // true
environment = 'prod';
transport = realtimeTransportFactory.createTransport();
console.log(transport instanceof WebSocketTransport); // true
window.WebSocket = null;
transport = realtimeTransportFactory.createTransport();
console.log(transport instanceof AjaxTransport); // true
var Clock = function () {};
Clock.prototype.getTime = function () {
return new Date().getTime();
};
// logs each call to methods of underlying object
var LoggingDecorator = function (target) {
this.target = target;
}
LoggingDecorator.prototype.getTime = function () {
var time = this.target.getTime();
console.log('getTime called, return value:', time);
return time;
};
// caches return values from underlying object
var CachingDecorator = function (target) {
this.target = target;
}
CachingDecorator.prototype.getTime = function () {
if (!this.cachedTime) {
this.cachedTime = this.target.getTime();
}
return this.cachedTime;
};
var clock = new Clock();
var decoratedClock = new CachingDecorator(new LoggingDecorator(clock)); // xzibit is happy
var interval = setInterval(function () {
console.log('clock value', clock.getTime());
console.log('decorated clock value', decoratedClock.getTime());
;}, 1000);
setTimeout(function () {
clearInterval(interval);
}, 2500);
// module1.js
define('module1', function () {
return 'module1';
});
<script data-main="js/init" src="js/library/require.js"> < / script >
// module2.js
define('module2', function () {
return 'module2';
});
// module3.js
define('module3', ['module1', 'module2'], function (module1, module2) {
return ['module3', module1, module2].join(' + ');
});
// app entry point
// init.js
require('module3', function (module3) {
console.log(module3);
// outputs: module3 + module1 + module2
});