snippetjavascriptMinor
Compose in Javascript - Go ahead with this example?
Viewed 0 times
thisjavascriptwithexamplecomposeahead
Problem
I'm trying to use the good parts of Javascript and dont follow the classical inheritance.
I studied and created this example of compose in Javascript, https://gist.github.com/fernandoperigolo/7789866.
My question is. You think this example have a good implementations of composition? Can i go ahead with it? If not, What you suggest?
```
(function(){
// Adding compose to Function prototype
Function.prototype.compose = function(argFn) {
var fnToCall = this;
return function() {
// This line is really complex and i don't know exactly what this line do
return fnToCall.call(this, argFn.apply(this,arguments));
}
}
// Eletronic atributes and methods
var asEletronic = function(){
this.voltage = '220v';
this.power = false;
this.switchPower = function(){
if (this.power === true) {
this.power = false;
console.info('Eletronic are off now.');
}else{
this.power = true;
console.info('Eletronic are on now.');
};
}
return this;
};
// Sound Reproducer atributes and methods
var asSoundReproducer = function(){
this.watts = 60;
this.playSound = function(sound){
console.info('Playing the sound: '+sound);
};
return this;
};
// All sound reproducer is a eletronic
// Composing first level
asSoundReproducer = asSoundReproducer.compose(asEletronic)
// Micro System atributes and methods
// Not used, just example
var asMicroSystem = function(){
this.cd = false;
this.mp3 = true;
return this;
};
// TV atributes and methods
var TV = function(){
this.pol = 42;
this.hdmi = true;
return this;
};
// Compose a TV with full resources
// Compose second level, asSoundReproducer is a composed object
// This line looks me strange...
TV = TV.compose(asSoundReproducer);
// Create a new TV
var myTV = new TV();
// Looking my TV
console.log(myTV);
// Call a Eletronic method
myTV.switchPower();
// Call a Sou
I studied and created this example of compose in Javascript, https://gist.github.com/fernandoperigolo/7789866.
My question is. You think this example have a good implementations of composition? Can i go ahead with it? If not, What you suggest?
```
(function(){
// Adding compose to Function prototype
Function.prototype.compose = function(argFn) {
var fnToCall = this;
return function() {
// This line is really complex and i don't know exactly what this line do
return fnToCall.call(this, argFn.apply(this,arguments));
}
}
// Eletronic atributes and methods
var asEletronic = function(){
this.voltage = '220v';
this.power = false;
this.switchPower = function(){
if (this.power === true) {
this.power = false;
console.info('Eletronic are off now.');
}else{
this.power = true;
console.info('Eletronic are on now.');
};
}
return this;
};
// Sound Reproducer atributes and methods
var asSoundReproducer = function(){
this.watts = 60;
this.playSound = function(sound){
console.info('Playing the sound: '+sound);
};
return this;
};
// All sound reproducer is a eletronic
// Composing first level
asSoundReproducer = asSoundReproducer.compose(asEletronic)
// Micro System atributes and methods
// Not used, just example
var asMicroSystem = function(){
this.cd = false;
this.mp3 = true;
return this;
};
// TV atributes and methods
var TV = function(){
this.pol = 42;
this.hdmi = true;
return this;
};
// Compose a TV with full resources
// Compose second level, asSoundReproducer is a composed object
// This line looks me strange...
TV = TV.compose(asSoundReproducer);
// Create a new TV
var myTV = new TV();
// Looking my TV
console.log(myTV);
// Call a Eletronic method
myTV.switchPower();
// Call a Sou
Solution
Interesting question,
from your comments inside the code you seem to not have written the code or have heavily borrowed from somebody else's code..
From a high level I have only a few misgivings:
This counter proposal is more complicated, but handles multiple constructors in 1 go, amd provides support for parameters and
from your comments inside the code you seem to not have written the code or have heavily borrowed from somebody else's code..
From a high level I have only a few misgivings:
- Do not modify standard JS objects, so do not add
composeto the prototype ofFunction, I grant you that it looks cool but it will bite you at some point
myTV instanceof asSoundReproducerdoes not work, so figuring what kind of object you are dealing with can be painful ( this is a drawback from not using standard js OO )
- You have some provision for passing parameters to functions with
argFn.apply(this,arguments)but the function signatures might look ugly since you do not cut outargFnfromarguments
- When reading up on composing, I prefer much to be able to compose in one go like
TV = compose( asSoundReproducer, asMicroSystem );
- I am not sure what
asstands for in your function names, I would drop anything that resembles Hungarian notation.
This counter proposal is more complicated, but handles multiple constructors in 1 go, amd provides support for parameters and
typeof.function merge(object, boltOn) {
//Simply merge the properties of boltOn into object, overriding existing properties
for(var property in boltOn)
if(boltOn.hasOwnProperty(property))
object[property] = boltOn[property];
return object;
}
function compose(/*Constructor1, Constructor2, ..*/) {
//Keep a closure reference for later
var constructorReferences = arguments;
return function ComposedConstructor(/*parameter1, parameter2, ..*/) {
//Clone the constructors, we will modify the clones
var constructorClones = Array.prototype.slice.call(constructorReferences).map(function(Constructor) {
return new Object(Constructor);
});
var constructor = constructorClones.pop();
//Set up the prototype chain, without loosing the original prototypes thru `merge`
while(constructorClones.length) {
var nextConstructor = constructorClones.pop();
nextConstructor.prototype = merge(new constructor(arguments), nextConstructor.prototype);
constructor = nextConstructor;
}
//Call the first constructor with the arguments provided to the constructor
constructor = constructor.bind.apply(constructor, [null].concat(Array.prototype.slice.call(arguments)));
return new constructor();
};
}
function A(name) {
this.a = name;
console.log(arguments);
}
A.prototype.sayA = function() {};
function B() {
this.b = 2;
console.log(arguments);
}
B.prototype.sayB = function() {};
function C() {
this.c = 3;
console.log(arguments);
}
C.prototype.sayC = function() {};
var O = compose(A, B, C);
var o = new O('Samsung');
// {[object Object] { a: "Samsung",b: 2,c: 3,sayA: function,sayB: function,sayC: function}
console.log(o);
console.log(o instanceof A); //true
console.log(o instanceof B); //true
console.log(o instanceof C); //trueCode Snippets
function merge(object, boltOn) {
//Simply merge the properties of boltOn into object, overriding existing properties
for(var property in boltOn)
if(boltOn.hasOwnProperty(property))
object[property] = boltOn[property];
return object;
}
function compose(/*Constructor1, Constructor2, ..*/) {
//Keep a closure reference for later
var constructorReferences = arguments;
return function ComposedConstructor(/*parameter1, parameter2, ..*/) {
//Clone the constructors, we will modify the clones
var constructorClones = Array.prototype.slice.call(constructorReferences).map(function(Constructor) {
return new Object(Constructor);
});
var constructor = constructorClones.pop();
//Set up the prototype chain, without loosing the original prototypes thru `merge`
while(constructorClones.length) {
var nextConstructor = constructorClones.pop();
nextConstructor.prototype = merge(new constructor(arguments), nextConstructor.prototype);
constructor = nextConstructor;
}
//Call the first constructor with the arguments provided to the constructor
constructor = constructor.bind.apply(constructor, [null].concat(Array.prototype.slice.call(arguments)));
return new constructor();
};
}
function A(name) {
this.a = name;
console.log(arguments);
}
A.prototype.sayA = function() {};
function B() {
this.b = 2;
console.log(arguments);
}
B.prototype.sayB = function() {};
function C() {
this.c = 3;
console.log(arguments);
}
C.prototype.sayC = function() {};
var O = compose(A, B, C);
var o = new O('Samsung');
// {[object Object] { a: "Samsung",b: 2,c: 3,sayA: function,sayB: function,sayC: function}
console.log(o);
console.log(o instanceof A); //true
console.log(o instanceof B); //true
console.log(o instanceof C); //trueContext
StackExchange Code Review Q#36965, answer score: 2
Revisions (0)
No revisions yet.