Composition, Inheritance, and Aggregation in JavaScript - javascript

There is a lot of information about composition vs inheritance online, but I haven't found decent examples with JavaScript. Using the below code to demonstrate inheritance:
function Stock( /* object with stock names and prices */ ) {
for (var company_name in arguments[0]) {
// copy the passed object into the new object created by the constructor
this[company_name] = arguments[0][company_name];
}
}
// example methods in prototype, their implementation is probably redundant for
// this question, but list() returns an array with toString() invoked; total()
// adds up the stock prices and returns them. Using ES5 feature to make
// inherited properties non-enumerable
Stock.prototype = {
list: function () {
var company_list = [];
for (var company_name in this)
company_list.push(company_name);
return company_list.toString();
},
total: function () {
var price_total = 0;
for (var company_name in this)
price_total += this[company_name];
return '$' + price_total;
}
};
Object.defineProperties(Stock.prototype, {
list: { enumerable: false },
total: { enumerable:false }
});
var portfolio = new Stock({ MSFT: 25.96, YHOO: 16.13, AMZN: 173.10 });
portfolio.list(); // MSFT,YHOO,AMZN
portfolio.total(); // $215.19
(To make the code smaller, you can leave out the method implementations, like: Stock.total = function(){ /* code */ } I just put them in there to be fancy). If composition is favored for a lot of situations in OOP, how come most people using JavaScript seem to only use prototypes and inheritance? I did not find a lot of information about composition in JavaScript online, only in other languages.
Can someone give me an example using the above code to demonstrate composition and aggregation?

The language is irrelevant when dealing with composition vs inheritance. If you understand what class is and what an instance of a class is, then you have all you need.
Composition is simply when a class is composed of other classes; or to say it another way, an instance of an object has references to instances of other objects.
Inheritance is when a class inherits methods and properties from another class.
Let's say you have two functionality, A and B. You want to define a third functionality, C, that has some or all of both A and B. You could either make C extend from B and A, in which case C has everything B and A has because C isA B and A, or you can make each instance of C have an instance of A and an instance of B, and invoke items on those functionalities. In the latter case, each instance C in effect wraps an instance of B and an instance of A.
Of course, depending on the language, you might not be able to have a class extend from 2 classes (e.g. Java doesn't support multiple inheritance), but that's a language specific detail that has nothing to do with the concept.
Now, for the language specific details...
I used the word class, but javascript has no notion of Class as such. It has objects, and thats it (other than the simple types). Javascript uses prototypal inheritance, which means it has a way of efficiently defining objects and the methods on those objects (this is the topic for another question; you can search SO as there are already answers.)
So going with our example above, you have A, B, and C.
For inheritance, you would have
// define an object (which can be viewed as a "class")
function A(){}
// define some functionality
A.prototype.someMethod = function(){}
If you wanted C to extend A, you would do
C.prototype = new A();
C.prototype.constructor = A;
Now every instance of C would have the method someMethod, because every instance of C "isA" A.
Javascript doesn't have multiple inheritance* (more on this later), so you can't have C extend both A and B. You can use composition, however, to give it the functionality. Indeed, this is one of the reasons composition is preferred by some over inheritance; there are no limits on combining functionality (but this isn't the only reason).
function C(){
this.a = new A();
this.b = new B();
}
// someMethod on C invokes the someMethod on B.
C.someMethod = function(){
this.a.someMethod()
}
So there are your simple examples for both inheritance and composition. However, this is not the end of the story. I said before that Javascript does not support multiple inheritance, and in a sense it doesn't, because you can't base the prototype of an object off the prototypes of multiple objects; i.e. you can't do
C.prototype = new B();
C.prototype.constructor = B;
C.prototype.constructor = A;
because as soon as you do the third, line, you just undid the the second line. This has implications for the instanceof operator.
However, this doesn't really matter, because just because you can't redefine the constructor of an object twice, you can still add any methods you want to the prototype of an object. So just because you can't do the above example, you can still add anything you want to C.prototype, including all the methods on the prototypes of both A and B.
Many frameworks support this and make it easy. I do a lot of Sproutcore work; with that framework you can do
A = {
method1: function(){}
}
B = {
method2: function(){}
}
C = SC.Object.extend(A, B, {
method3: function(){}
}
Here I defined functionality in object literals A and B, and then added the functionality of both to C, so every instance of C has methods 1, 2, and 3. In this particular case, the extend method (provided by the framework) does all the heavy lifting of setting up the prototypes of the objects.
EDIT -- In your comments, you bring out a good question, namely "If you use composition, how do you reconcile the scope of the main object against the scope of the objects of which the main object is composed".
There are a bunch of ways. The first is simply to pass arguments. So
C.someMethod = function(){
this.a.someMethod(arg1, arg2...);
}
Here you are not messing with scopes, you are simply passing arguments around. This is a simple and very viable approach. (the arguments can come from this or be passed in, whatever...)
Another way to do it would be to use the call (or apply) methods of javascript, which basically allows you to set the scope of a function.
C.someMethod = function(){
this.a.someMethod.call(this, arg1, arg2...);
}
to be a bit more clear, the following is equivalent
C.someMethod = function(){
var someMethodOnA = this.a.someMethod;
someMethodOnA.call(this, arg1, arg2...);
}
In javascript, functions are object, so you can assign them to variables.
the call invocation here is setting the scope of someMethodOnA to this, which is the instance of C.

...
Can someone give me an example using the above code to demonstrate
composition and aggregation?
At first glance the provided example does not seem to be the best
choice in order to demonstrate composition in JavaScript. The prototype
property of the Stock constructor function still remains the ideal
place for both methods total and list for both do access any stock
object's own properties.
What can be done is decoupling the implementations of these methods
from the constructors prototype and providing them back exactly there -
yet in an additional form of code reuse - Mixins ...
example:
var Iterable_listAllKeys = (function () {
var
Mixin,
object_keys = Object.keys,
listAllKeys = function () {
return object_keys(this).join(", ");
}
;
Mixin = function () {
this.list = listAllKeys;
};
return Mixin;
}());
var Iterable_computeTotal = (function (global) {
var
Mixin,
currencyFlag,
object_keys = global.Object.keys,
parse_float = global.parseFloat,
aggregateNumberValue = function (collector, key) {
collector.value = (
collector.value
+ parse_float(collector.target[key], 10)
);
return collector;
},
computeTotal = function () {
return [
currencyFlag,
object_keys(this)
.reduce(aggregateNumberValue, {value: 0, target: this})
.value
.toFixed(2)
].join(" ");
}
;
Mixin = function (config) {
currencyFlag = (config && config.currencyFlag) || "";
this.total = computeTotal;
};
return Mixin;
}(this));
var Stock = (function () {
var
Stock,
object_keys = Object.keys,
createKeyValueForTarget = function (collector, key) {
collector.target[key] = collector.config[key];
return collector;
},
createStock = function (config) { // Factory
return (new Stock(config));
},
isStock = function (type) {
return (type instanceof Stock);
}
;
Stock = function (config) { // Constructor
var stock = this;
object_keys(config).reduce(createKeyValueForTarget, {
config: config,
target: stock
});
return stock;
};
/**
* composition:
* - apply both mixins to the constructor's prototype
* - by delegating them explicitly via [call].
*/
Iterable_listAllKeys.call(Stock.prototype);
Iterable_computeTotal.call(Stock.prototype, {currencyFlag: "$"});
/**
* [[Stock]] factory module
*/
return {
isStock : isStock,
create : createStock
};
}());
var stock = Stock.create({MSFT: 25.96, YHOO: 16.13, AMZN: 173.10});
/**
* both methods are available due to JavaScript's
* - prototypal delegation automatism that covers inheritance.
*/
console.log(stock.list());
console.log(stock.total());
console.log(stock);
console.dir(stock);
There is a lot of information about composition vs inheritance
online, but I haven't found decent examples with JavaScript.
...
I did not find a lot of information about composition in JavaScript
online, only in other languages.
...
Maybe the search query was not specific enough but even in 2012
searching for "JavaScript Mixin composition" should have led into
a not that bad direction.
...
If composition is favored for a lot of situations in OOP, how
come most people using JavaScript seem to only use prototypes
and inheritance?
Because most of them use, what they got tought and/or what they
are familar with. Maybe there should be more knowledge spread
about JavaScript as delegation based language too and what can
be achieved with it.
appendix:
This are related threads, recently updated and hopefully helping ...
stackoverflow.com :: How to use mixins properly in Javascript
stackoverflow.com :: Traits in javascript
stackoverflow.com :: Javascript Distinguish between Composition vs. Inheritance

I think I can show you how to rewrite your code in "object composition" fashion by using plain JavaScript (ES5). I use factory functions instead of constructor functions for creating an object instance, so no new keyword needed. That way, I can favour object augmentation (composition) over classical/pseudo-classical/prototypal inheritance, so no Object.create function is called.
The resulting object is a nice flat-composed object:
/*
* Factory function for creating "abstract stock" object.
*/
var AbstractStock = function (options) {
/**
* Private properties :)
* #see http://javascript.crockford.com/private.html
*/
var companyList = [],
priceTotal = 0;
for (var companyName in options) {
if (options.hasOwnProperty(companyName)) {
companyList.push(companyName);
priceTotal = priceTotal + options[companyName];
}
}
return {
/**
* Privileged methods; methods that use private properties by using closure. ;)
* #see http://javascript.crockford.com/private.html
*/
getCompanyList: function () {
return companyList;
},
getPriceTotal: function () {
return priceTotal;
},
/*
* Abstract methods
*/
list: function () {
throw new Error('list() method not implemented.');
},
total: function () {
throw new Error('total() method not implemented.');
}
};
};
/*
* Factory function for creating "stock" object.
* Here, since the stock object is composed from abstract stock
* object, you can make use of properties/methods exposed by the
* abstract stock object.
*/
var Stock = compose(AbstractStock, function (options) {
return {
/*
* More concrete methods
*/
list: function () {
console.log(this.getCompanyList().toString());
},
total: function () {
console.log('$' + this.getPriceTotal());
}
};
});
// Create an instance of stock object. No `new`! (!)
var portofolio = Stock({MSFT: 25.96, YHOO: 16.13, AMZN: 173.10});
portofolio.list(); // MSFT,YHOO,AMZN
portofolio.total(); // $215.19
/*
* No deep level of prototypal (or whatsoever) inheritance hierarchy;
* just a flat object inherited directly from the `Object` prototype.
* "What could be more object-oriented than that?" –Douglas Crockford
*/
console.log(portofolio);
/*
* Here is the magic potion:
* Create a composed factory function for creating a composed object.
* Factory that creates more abstract object should come first.
*/
function compose(factory0, factoryN) {
var factories = arguments;
/*
* Note that the `options` passed earlier to the composed factory
* will be passed to each factory when creating object.
*/
return function (options) {
// Collect objects after creating them from each factory.
var objects = [].map.call(factories, function(factory) {
return factory(options);
});
// ...and then, compose the objects.
return Object.assign.apply(this, objects);
};
};
Fiddle here.

Related

JavaScript efficient solution for multi-inheritance

Why this question is not a duplicate
This answer javascript inheritance from multiple objects does not solve my problem (although it has been marked as a duplicate of my previous question), because it is not scalable as it violates the DRY principle.
For this to work, one would have to manually reference each method like this :
Foo2.prototype.a = function() { /*code...*/};
Foo2.prototype.b = function() { /*code...*/};
Foo2.prototype.c = function() { /*code...*/};
Foo2.prototype.d = function() { /*code...*/};
//and so on and so on...
And what if I have dozens of classes containing dozens of methods ? Should I really manually copy-paste the same reference for each and every class over and over again in my source code ? While this solution would work for a very low number of classes, it is just not usable in a large-scale application using dozens or hundreds of classes.
The problem I'm trying to solve
I'm trying to instantiate objects which must inherit all the properties and methods of Animal and Flying_object using new keyword.
var objA = new Fish(),
objB = new Bird(),
objC = new UFO();
Tricky part is Animal and Flying_object can NOT have a parent-child relationship.
I know JavaScript doesn't implement native methods for multi-inheritance, so I'm posting this question to get some help finding a custom, scalable solution to this problem.
Code example and expected behavior
var Living_being = function() { this.className = 'Living_being'; };
var Animal = function() {
this.className = 'Animal';
this.vector = {x: 0, y: 0};
}
Animal.prototype = new Living_being();
Animal.prototype.getClassName = function() { console.log('Instance of... '+ this.className); };
Animal.prototype.get_vector = function() { console.log(this.vector); }
var Flying_object = function() {
this.className = 'Flying_object';
this.value = 'some value';
}
Flying_object.prototype.getClassName = function() { console.log('Instance of... '+ this.className); };
Flying_object.prototype.get_val = function() { console.log(this.value); }
// So far so good...
var UFO = function() {};
UFO.protoype = new Flying_object(); //classical inheritance
var Fish = function() {};
Fish.protoype = new Animal(); //classical inheritance
// Now the tricky part: how to make Bird share all of the methods and properties of Animal and Flying_object ?
var Bird = function() {};
Bird.prototype = new ....(); //pseudocode where .... is a class containing all the properties of Animal and Flying_object
var instance = new Bird();
//expected result:
instance.getClassName();//--> Instance of...
instance.get_vector(); //--> {x: 0, y: 0}
instance.get_val(); //--> 'some value'
This is where I'm stuck. How can I make Bird inherit from BOTH Animal and Flying_object ?
Any insight would be greatly apprenciated.
Here is a working solution I came up with at some point and gave up because I though there might be a better solution.
#Mörre: I'm not sure this is what you advised me to do in the comments: is this what you called object composition ? Or am I going all wrong here ?
Demo: https://jsfiddle.net/Lau1989/4ba8yrc8/1/
function mix(classA, classB) {
var instanceA = new classA(),
instanceB = new classB();
for (var prop in instanceA) {
instanceB[prop] = instanceA[prop];
}
return instanceB;
}
var Bird = function() { this.className = 'Bird'; };
Bird.prototype = mix(Animal, Flying_object);
var instance = new Bird();
If you need inherit from few classes you can extend prototype Bird from Animal and Ufo using jquery function $.extend({});.
Example $.extend(Bird.prototype,Animal.prototype,UFO.prototype) or you can create custom extend function.If names properties or functions has same names , they will be rewrite.
I got this from documentation: Using Object.assign() extend only enumerable properties.The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties versus just copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters. For copying property definitions, including their enumerability, into prototypes Object.getOwnPropertyDescriptor() and Object.defineProperty() should be used instead.
JavaScript does not support the concept of multiple inheritance. It also does not implement syntax for mixin and/or trait based composition. But unlike the former, the latter can be achieved by e.g. function and delegation based mixin patterns.
Thus, one first needs to figure out which parts of a composable object system should build the 'is a' relationship and which parts are behavior ('can do' / 'has a') that might get reused by/at different parts/levels of the object system.
The OP already has done this work. The example code that will be provided below is just going to introduce different function based mixin patterns via providing implementations of some behaviors like withLivingBeingBasics and withFlyingAbility ... with the first mixin covering the OP's Living_being class and the second one covering Flying_object.
For better code reuse there are 2 additional mixins, withExposeClassName and withExposeVector that, for the reason of demonstration, compose into the withExposeClassNameAndVector mixin compound.
From this possible base setup, that follows the OP's example, one could continue with shaping the classes.
With the Animal class one is free of choosing where mixin composition shall take place. Following the provided original example, composition at class/prototype level is the better option instead of applying the behavior at construction/instantiation time from within the constructor.
After applying withExposeClassNameAndVector and withLivingBeingBasics to Animal.prototype, any animal instance via prototypal delegation is capable of being invoked at getClassName and getVector as well as at metabolize and reproduce. Thus, at this point, both mixin composition (explicit delegation via call to prototype) and inheritance (automatically running delegation via prototype chain) take place.
The Fish class is implemented easily. As with the OP's example one just follows a simplified inheritance pattern via Fish.prototype = new Animal;. In addition, as already featured with the Animal base class, a class' name gets assigned to its prototype object.
Bird repeats the base patterns of Fish with the exception of featuring its own vector property that now is three dimensional instead of the otherwise prototypal two dimensional one. And since a common bird is supposed to somehow feature flying behavior Bird.prototype has to acquire it from withFlyingAbility.
Following still the OP's example, Ufo also needs to have flying ability. And like a bird, an ufo too has to feature an own three dimensional vector property. Thus the property gets assigned at construction/instantiation time and all the needed behavior gets applied from withExposeClassNameAndVector and from withFlyingAbility to Ufo.prototype.
The provided approach intends to prove that ... the most atomar mixin implements exactly one behavior, ... mixins are not necessarily supposed to introduce state but a behavior might operate upon state, ... mixins can be composed from other mixins, ... they always get applied at object level, either to already existing objects or to the prototype object itself or at composition time from within a constructor function ...
var withLivingBeingBasics = (function () { // function based mixin
function metabolize() { // implement beahvior once.
console.log('every living being features some kind of metabolism.');
}
function reproduce() { // implement beahvior once.
console.log('every living being features some kind of reproduction.');
}
return function() {
this.metabolize = metabolize; // assign shared code.
this.reproduce = reproduce; //
}
}());
var withFlyingAbility = (function () {
function liftOffAerodynamically() {
this.vector.z = 5;
console.log('flying needs some kind of aerodynamic lift.');
}
function monitorAltitudeDifference() {
console.log('monitoring altitude difference : ', this.vector.z);
}
return function() {
this.liftOffAerodynamically = liftOffAerodynamically;
this.monitorAltitudeDifference = monitorAltitudeDifference;
}
}());
var withExposeVector = (function () {
function getVector() {
console.log('vector : ', this.vector);
}
return function() {
this.getVector = getVector;
}
}());
var withExposeClassName = (function () {
function getClassName() {
console.log('Instance of... ', this.className);
}
return function() {
this.getClassName = getClassName;
}
}());
var withExposeClassNameAndVector = function () { // mixin compound.
withExposeClassName.call(this);
withExposeVector.call(this);
}
function Animal() {
//withLivingBeingBasics.call(this); // mixing in for the given example is …
//this.className = 'Animal'; // … better at **class**/prototype level.
this.vector = {x: 0, y: 0};
}
// the many ways of augmenting the `prototype` ...
Object.assign(Animal.prototype, { className: 'Animal' });
//withExposeClassName.call(Animal.prototype);
//withExposeVector.call(Animal.prototype);
withExposeClassNameAndVector.call(Animal.prototype);
withLivingBeingBasics.call(Animal.prototype);
function Fish() {}
Fish.prototype = new Animal;
Object.assign(Fish.prototype, { className: 'Fish' });
function Bird() {
this.vector = {x: 0, y: 0, z: 0};
}
Bird.prototype = new Animal;
Object.assign(Bird.prototype, { className: 'Bird' });
withFlyingAbility.call(Bird.prototype);
function Ufo() {
this.vector = {x: 0, y: 0, z: 0};
}
Object.assign(Ufo.prototype, { className: 'Ufo' });
//withExposeClassName.call(Ufo.prototype);
//withExposeVector.call(Ufo.prototype);
withExposeClassNameAndVector.call(Ufo.prototype);
withFlyingAbility.call(Ufo.prototype);
var fish = new Fish;
var bird = new Bird;
var ufo = new Ufo;
console.log('(fish instanceof Animal) ? ', (fish instanceof Animal));
console.log('(fish instanceof Fish) ? ', (fish instanceof Fish));
fish.getClassName();
fish.metabolize();
fish.reproduce();
fish.getVector();
console.log('(bird instanceof Animal) ? ', (bird instanceof Animal));
console.log('(bird instanceof Bird) ? ', (bird instanceof Bird));
bird.getClassName();
bird.metabolize();
bird.reproduce();
bird.getVector();
bird.monitorAltitudeDifference();
bird.liftOffAerodynamically();
bird.monitorAltitudeDifference();
console.log('(ufo instanceof Ufo) ? ', (ufo instanceof Ufo));
ufo.getClassName();
ufo.getVector();
ufo.monitorAltitudeDifference();
ufo.liftOffAerodynamically();
ufo.monitorAltitudeDifference();
.as-console-wrapper { max-height: 100%!important; top: 0; }
For further reading on SO one might give the following related questions and solutions a chance ...
What are the practical differences between Mixins and Inheritance in Javascript?
Mixins for ES6 classes, transpiled with babel
Traits in javascript
Accessors Composition in ES6 Classes

What's the recommended way of creating objects in NodeJS?

I'm building a composite for request module, however I'm not sure what's the best practice regarding building objects in JS for Node.
Option 1:
function RequestComposite(request) {
return {
get: function (url) { return request.get(url); }
}
}
var comp = RequestComposite(request);
Note: I know that i should call a CB in async way, but for the ease of explaination I return it...
Option 2:
function RequestComposite(request) {
this.request = request;
}
RequestComposite.prototype.get = function (url) { return this.request.get(url); };
var comp = new RequestComposite(request);
Option 3:
var RequestComposite = {
init: function (request) { this.request = request; },
get: function (url) { return request.get(url); }
}
var comp = Object.create(RequestComposite).init(request);
I tried to find my way around, however I got even more confused about how should I use objects...
Would the answer be different if I want to use objects for browsers?
Thanks.
The most efficient way is the following:
Put all the essential initialisation in the constructor (e.g. validate constructor parameters, set properties, etc).
Set methods in the .prototype property of the constructor. Why? Because this prevents from re-writing each method each time you create an object. This way you recycle the same prototype for each object you create. Efficient in memory and sparing coding time.
Do not use closures for private properties. Why? It is slow, and prevents you from using this object in an inheritance chain (the pseudo-private vars don't belong to the object, they're just accessible). It is instead common practice to use an underscore when declaring an object property, to indicate it is a _private property that should not be accessed from outside.
Use new instead of Object.create. It's easier to remember if you are used to other OOP languages; and at the end new uses Object.create under the hood.
In other words, something like this:
var Person = function (name) {
this._name = name;
};
Person.prototype.sayHello = function () {
alert('My name is: ' + this._name);
};
var john = new Person('John');
john.sayHello();
EDIT
Some extra information:
Object.create vs new. Benchmark here. Although the question is for Node.js, I think the same behaviour is to be expected. (any correction is welcome)
Closures to emulate private properties: You can read about in this question.. The point that the private/closure properties do not belong to the object is a programming fact: they are accessible by the object methods but do not belong to the object. When using inheritance, that is a big mess. Besides, only methods that are declared in the constructor have access to the closure. Methods defined in the prototype do not.
Defining methods in the constructor or the prototype property: read this question, and take a look of this benchmark
EDIT 15/04/2016
The points I made here three years ago are still right from a performance point of view, but my opinion about what is the "recommended way" has changed a little in the meanwhile. Factory functions are in general a good option, which would be the OP's first approach. Just an example:
function Person(name) {
return {
sayHello: function () { alert('My name is: ' + name); }
};
}
and then just do:
var p = Person('John');
In this case you trade flexibility (no new coupling, ease of composition with other "mix-ins") and simplicity (no this mess, easy object instantiation) for some speed and memory. In general they are perfectly valid. If you have performance issues, and those are because of this way of creating objects, revert to another method. The Object.create approach is also good, falling somehow in the middle of new and factory functions (side note: the new class syntax is syntactic sugar for new+ prototype)
Summing up: my recommended way is starting from the simplest and easiest way of creating objects (factory functions) and then fall to other methods when you hit performance issues (which in most of cases is never).
There are many ways to create "Class" and "Object" in JS. I prefer this way:
var MyObject =
function(args) {
// Private
var help = "/php/index.php?method=getHelp";
var schedule = "/php/index.php?method=getSchedules";
var ajax = function(url, callback, type) {
//....
}
// Public
this.property = 0;
this.getInfo = function() {
// ...
}
// Constructor
function(data) {
this.property = data;
}(args);
};
var o = new MyObject();
Note: If you are more familiar with OOP syntax, you can also use class which is just syntactical sugar over existing prototype-based way.
Performance Comparison between 4 ways of creating object - with constructor (Chrome 61 - https://jsperf.com/create-object-ways)
Option A: Using return (Fastest 3x)
Option B: Using {key:value} (1.5x)
Option C: Using prototype (1x) <- Base
Option D: Using class (1.02x)
Option A seams to perform best. Note that some of the performance boost is because it avoids use of new or object.create. So just to have a fair trial, here is another test between method-only objects without constructor and properties.
Performance Comparison between 4 ways of creating methods-only object (Chrome 61 - https://jsperf.com/create-static-object-ways)
Option A: Using return (3.2x)
Option B: Using {key:value} (Fastest 3.3x)
Option C: Using prototype (1.8x)
Option D: Using class (1.9x)
Option B outperformed Option A a little. Also the bottleneck caused by object.create was more then new.
Best Practice
Option A (using return) is best performing in both the scenarios. This way can get little messy if you have many methods and properties.
I prefer to divide constructor & properties in separate object using Option A and methods in another object using Option B. This approach does need to send an extra instance reference in parameters but can be useful if you have multiple objects using same properties & constructor (Some OOP inheritance can also be achieved).
Example:
// Constructor & Properties Object (Using option A)
var UserData = function(request){
// Constructor
if ( request.name )
var name = request.name;
else
var name = 'Not Available';
if ( request.age )
var age = request.age;
else
var age = null;
// Return properties
return {
userName: name,
userAge: age
};
};
// Object methods (Using Option B)
var Adults = {
printName: function(instance){ // Read propery example
console.log( 'Mr. ' + instance.userName );
},
changeName: function(instance, newName){ // Write property example
instance.userName = newName;
},
foo: function(){
console.log( 'foo' );
}
};
// Object methods (Using Option B)
var Children = {
printName: function(instance){
console.log( 'Master ' + instance.userName );
},
bar: function(){
console.log( 'bar' );
}
}
// Initialize
var userData = UserData ( {name: 'Doe', age: 40} );
// Call methods
Adults.printName(userData); // Output 'Mr. Doe'
Children.printName(userData); // Output 'Master Doe'
Adults.foo(); // Output 'foo'
Children.bar(); // Output 'bar'
Adults.changeName(userData, 'John');
Adults.printName(userData); // Output 'Mr. John'

JavaScript OOP classes and declarations

Im finding it really difficult to grasp OOP in javascript.
Normally I would expect to have to create a class, and then create objects from that class.
However, according to one tutorial the following makes an object.
var egg = {}
Have I not just made an object named egg without actually making a class.
If thats the case how would I make multiple objects from an object :S
Also according to a different tutorial an object is made like below, which is completely difference to what I was told above :S
var Block = function(){
}
Can anyone help me unravel my confusion :(
Both of the above examples are correct. to put it simply EVERYTHING in javascript is an object. classes do not exist but there are many ways to imitate them. my favorite method is as follows:
var myClass = function() { <----------------------------- class declaration
var prop1,
prop2, <------------------------------------ private properties
prop3;
var addMe = function( arg1, arg2 ) { <------------ private method
var result = arg1 + arg2;
return result;
}
var obj = { <------------------------------------- constructor method
Prop1: prop1,
Prop2: value2, <----------------------------- public properties
Prop3: value3,
Method: function() { <------------------------ public method
obj.prop3 = obj.prop1 + obj.prop2;
return obj.prop3;
}
}
obj.Prop4 = addme( prop1, prop2 ); <-------------- public property set
with the private method
return obj;
}
var myClassObj = new myClass;
myClassObj is now an object of myClass with four public properties
Prop1, Prop2, Prop3, Prop4 and one public method called Method
Javascript is a different language than those that you have learned so far. You can't expect things to work exactly as they do when you change languages.
A quick sneak peek: in javascript, you can assign a function to a variable. I bet on those other languages you have used, that was not possible:
var myCounter = 1;
var myFunction = function(x){ return x + 1; };
Going back to your question: In javascript there are no "real classes". There are just objects. I know this might sound confusing at first.
Javascript's object model is called "prototypal inheritance". It's different than "classical" (pun intended) inheritance. And it is also not very cleanly implemented.
Basically, you start with one reduced set of objects (Array, Function, Object, etc. are Objects, not classes) and then you use those objects to build others. The relationships between them can be "class-and-instance-like", but they don't have to. They can be other kinds of relationships, too.
Since there are no classes, you can't create them. But you can create a regular object, assign it to the variable Car, and just think "I'm going to use this object to create lots of other objects. And those other objects will have some attributes by default, like methods and stuff, so that they behave like cars". And the language allows you do do that. Car will behave like a class does in other languages, and the objects it produces will be "like instances of Car".
To javascript, though, they will look like objects with some relationships between them.
In a way, prototypal inheritance is a "superset" of classical inheritance. You can do classical inheritance, but also other things.
Have I not just made an object named egg without actually making a
class.
That's right. All you're doing there is instantiating the base Object object - you've not made anything that you can make instances of.
In JavaScript there is no formalised concept of classes - there is merely a simulation of them, achieved by instantiating rather than invoking functions.
function Animal() { this.animal = true; }
Animal.prototype.sayHi = function() { alert(this.name+' says hi!'); }
function Dog(name) { this.name = name; }
Dog.prototype = new Animal();
...
var fido = new Dog('Fido');
fido.sayHi(); //"Fido says hi!";
Note the 4th line is just one of several means of simulating inheritance.
So in JavaScript, classes and functions are both just functions. There is nothing inherent to prevent a function intended for instantiation from being called without the new operator, nor visa-versa.
In the former case, the common workaround is to check that the constructor is the 'class' (if invoked and not instantiated, the constructor will be Object) and re-route as necessary:
function Dog(name) {
//if we weren't instantiated, the constructor will be Object, not Dog
if(this.constructor != Dog) return new Dog(name);
this.name = name;
}
var fido = Dog(); //bad - invocation should be instantiation
Yes var egg = {} is an object, but its not an instance of an object.
In javascript, simply saying something in that way is basically js's idea of a singleton, meaning it is exactly what it equals.
//this is a js singleton, and all properties of this object are public.
var egg = {
name: 'humpty',
smush: function() { console.log('splat!'); },
weight: '4oz'
};
console.log(egg.weight); //4oz
whereas, the more traditional type of object would be making it a function that you can then instantiate:
var Egg = function( name, weight ) {
var name = name;
this.smush = function() { console.log('splat!'); }
this.weight = weight;
};
var e2 = new Egg('dumpty','6oz');
console.log(e2.name); //will not return name. (since i wrote var name and not this.name, its "private" and thus cannot be accessed.)
console.log(e2.weight); //4oz
You want to look at "Prototypal Inheritance" for JavaScript.
http://www.crockford.com/javascript/inheritance.html
Create an object oriented with jQuery. Make use of the constructor() method and access public and private methods from within the class scope.
/*
* myClass
*/
var myClass = function(options){
/*
* Variables accessible
* in the class
*/
var vars = {
myVar : ''
};
/*
* Can access this.method
* inside other methods using
* root.method()
*/
var root = this;
/*
* Constructor
*/
this.construct = function(options){
$.extend(vars , options);
};
/*
* Public method
* Can be called outside class
*/
this.myPublicMethod = function(){
console.log(vars.myVar);
myPrivateMethod();
};
/*
* Private method
* Can only be called inside class
*/
var myPrivateMethod = function() {
console.log('private method called');
};
/*
* Pass options when class instantiated
*/
this.construct(options);
};
/*
* USAGE
*/
/*
* Set variable myVar to new value
*/
var newMyClass = new myClass({ myVar : 'new Value' });
/*
* Call myMethod inside myClass
*/
newMyClass.myPublicMethod();

Javascript: Prototyping a function with arguments for performance

In John Resig's post on Simple "Class" Instantiation in Javascript, he states:
"...if you have a frequently-accessed function (returning an object) that you want people to interact with, then it's to your advantage to have the object properties be in the prototype chain and instantiate it. Here it is, in code:"
// Very fast
function User(){}
User.prototype = { /* Lots of properties ... */ };
// Very slow
function User(){
return { /* Lots of properties */ };
}
I would like to apply this to a function like the following (which happens to live inside a "class" declaration)
//...
this.get_subscription = function(args)
{
return {
property_one: "value",
property_two: {
sub_prop: args.something
}
}
}
but have no idea where to put the args. If I do
this.get_subscription = function(args) {}
this.get_subscription.prototype = {
property_one: "value"
//...
}
it'll say args are undefined. I've tried several variants, none of which work. How should I properly do this, in a way that doesn't put args in the parent class's scope?
You seem to misunderstand the point of prototype. Prototype holds methods and fields that should be common to all instances of the object. Therefore, if property_two is based upon args passed to the constructor, then it does not belong to the prototype!
After all, in this code
this.get_subscription = function(args) {}
this.get_subscription.prototype = {
property_one: "value"
//...
}
first, the function get_subscription is created, then its prototype is set to the object literal. There is no args until you call the constructor, so it does not make sense to do something with the args in the prototype.
So, your usual javascript object should look like this example - a 2D point class.
function Point(x, y) {
/* In constructor:
* initialize fields that are related to the constructor parameters
* and are different for different instances
*/
this.x = x;
this.y = y;
}
// in prototype, define fields that are common to all instances
Point.prototype.RED = '#FF0000';
/* in prototype, also define the methods; as they can use the "this" keyword,
* they can reference their own instance, so you don't have to include them
* in each instance manually
*/
Point.prototype.toString = function() { return '[' + this.x + ', ' + this.y + ']'; };
Yes, that's the drawback of the "everything-to-prototype"-idea: You don't have access to the constructor arguments - they are only available inside the function body (exept you put them into a public property there). Everything that needs to use them does not belong to the prototype; you only will fill "default properties" on the prototype (usually methods that are common to all instances).
I think that you don't need that anyway in here. The pattern is only useful for real constructor functions, which you don't seem to have here (I then would expect this.Subscription). Also, the promised "performance boost" is negligible.
If you really would want to use it in here, it would be:
function Class() {
this.Subscription = function(args) {
this.propertyTwo = {
subprop: args.something
};
};
this.Subscription.prototype = {
property_one: "value",
property_two: {}
};
}
// a method callable without the "new" operator:
Class.prototype.get_subscription = function(args) {
return new this.Subscription(args);
}
usage:
var object = new Class();
var sub = new object.Subscription();
var sub2 = new object.Subscription();
// the promised boost is less memory usage for:
sub.propertyOne === object.Subscription.prototype.propertyOne === sub2.propertyOne;
Also care for Crockford's Prototypal inheritance - Issues with nested objects when you attempt to set/change/delete properties on the propertyTwo-Object(s).

Choosing an OOP pattern in javascript

I've put these together with the help of others and several resources. I've made a fiddle of everything, and the stripped down code is posted below.
Basically I've learned how to use each of these patterns but I'm curious about the more fundamental differences between these approaches. Downstream code is practically identical with any of these patterns, but is there a reason why one should use one over another, beyond personal preference? Also though I've tried to gather up the most common patterns, please suggest your own if it's better.
Pattern 1 (Object Based):
var mouseDiff = {
"startPoint" : {"x" :0, "y" : 0},
"hypotenuse" : function(a,b) {
// do something
},
"init" : function(){
// do something
}
}
mouseDiff.init();
Pattern 2 (Most traditional as far as I know):
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
}
MouseDiff.prototype.init = function() {
// do something
}
var myMouse = new MouseDiff;
myMouse.init();
Pattern 3 (Making use of closure):
var MouseDiff2 = (function() {
var startPoint = {"x" :0, "y" : 0};
var hypotenuse = function(a,b) {
// do something
};
return {
hypotenuse: hypotenuse,
init : function(){
// do something
}
};
}());
MouseDiff2.init();
Pattern 1 is a singleton. If you only need one such object, it's just fine.
Pattern 2 builds new objects, and takes advantage of the prototype object so that when a new MouseDiff object is created, it will not create new copies of the functions (which are themselves data in JavaScript).
Pattern 3 requires more memory in comparison to a regular singleton but it offers static privacy.
I like the following pattern, as it covers various features, though it is really a combination of the constructor (pattern 2) and closure (pattern 3):
var MouseDiff = (function () {
var aStaticVariable = 'Woohoo!';
// And if you really need 100% truly private instance
// variables which are not methods and which can be
// shared between methods (and don't mind the rather
// big hassle they require), see
// http://brettz9.blogspot.com/search?q=relator
// (see also the new plans for a Map/WeakMap in ECMAScript)
function _APrivateStaticMethod () {
alert(aStaticVariable);
}
// An instance method meant to be called on the
// particular object as via ".call(this)" below
function _APrivateInstanceMethod () {
alert(this.startPoint.x);
}
// Begin Constructor
function MouseDiff() {
this.startPoint = {"x" :0, "y" : 0};
}
MouseDiff.prototype.hypotenuse = function(a,b) {
// do something
};
MouseDiff.prototype.init = function() {
// do something
_APrivateStaticMethod(); // alerts 'Woohoo!'
_APrivateInstanceMethod.call(this); // alerts 0 (but if not
// called with this, _APrivateInstanceMethod's internal
// "this" will refer (potentially dangerously) to the
// global object, as in the window in the browser unless
// this class was defined within 'strict' mode in which
// case "this" would be undefined)
};
return MouseDiff;
}());
var myMouse = new MouseDiff;
myMouse.init();
I do not know enough about JavaScript to tell you what if any performance differences exist between these approaches. Here are just two differences between these I noticed. I'm sure there are others.
Pattern 1 creates one object with those properties, including attached methods. Pattern 2 allows us to easily create many objects with the same methods attached, without rewriting them.
Pattern 3 is like a factory. Instead of relying on prototype to automatically attach these methods, the factory just creates them anew and returns the object. The usage of a closure allows us to hide the "member variables" of the object. There is no way to access startPoint or hypotenuse() except through the "public" interface returned.
Whenever I answer these types of theoretical JavaScript questions, I always fear there is some technical detail I am forgetting or overlooking. If so, let me know, and I will fix the answer.
Pattern two is my personally preference because it is the closest to traditional object oriented programming and allows for easy inheritance.
This post by John Resig (the guy behind JQuery) uses that method...
http://ejohn.org/blog/simple-javascript-inheritance/
[edit]
In fact, I don't think methods 1 or 3 have any benefits. 1 is, as someone else said, a singleton and does not allow multiple instances and 3... I don't know where to start with 3.
There is one more possible way to do this.
var MouseDiff = {};
(function(context) {
var privateVarialble = 0;
context.hypotenuse = function() {
//code here
};
context.int = function() {
//code here
}
})(MouseDiff);
Here we simply pass the namespace as an argument to a self-invoking function. The privateVarialble variable is private because it does not get assigned to the context.
We can even set the context to the global object (with a one word change!). Inside brackets (MouseDiff) make it (this). This is a big asset for library vendors – who can wrap their features in a self-invoking function and leave it to the user to decide whether they should be global or not.
http://www.jsoops.net/ is quite good for oop in Js. If provide private, protected, public variable and function, and also Inheritance feature. Example Code:
var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public
pri.className = "I am A ";
this.init = function (var1)// constructor
{
pri.className += var1;
}
pub.getData = function ()
{
return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
+ ", ID=" + pro.getClassId() + ")";
}
pri.getClassName = function () { return pri.className; }
pro.getClassName = function () { return pri.className; }
pro.getClassId = function () { return 1; }
});
var newA = new ClassA("Class");
//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)
//***You can not access constructor, private and protected function
console.log(typeof (newA.init)); // undefined
console.log(typeof (newA.className)); // undefined
console.log(typeof (newA.pro)); // undefined
console.log(typeof (newA.getClassName)); // undefined
This has been answered elsewhere many times before but just to offer up some variety. ds.oop is a nice way to declare classes with constructors in javascript. It supports every possible type of inheritance (Including 1 type that even c# does not support) as well as Interfaces which is nice.
var Color = ds.make.class({
type: 'Color',
constructor: function (r,g,b) {
this.r = r; /* now r,g, and b are available to */
this.g = g; /* other methods in the Color class */
this.b = b;
}
});
var red = new Color(255,0,0); // using the new keyword to instantiate the class

Categories