I have an object that sits on the prototype, if it has a simple property like bar:3, then any instance can change bar without affecting other instances. However, if it has an object property instead (baz), any instance changing bar.x will be reflected on all other instances, I presume because objects are by reference.
Example object that sits on a prototype:
var foo = {
bar: 3, // single prop - this is okay
baz:{x: 4,y:5} // object prop - an instance can't change baz.x
};
My question - in the code below, how do I make porsche show "object prop: V12"?
var vehicle = {
colour: 'blue',
info: function() {
console.log('wheels:' + this.wheels + ' colour:' + this.colour);
}
};
var engine = {
size: 'V12', // single prop
type:{size: 'V12',fuel:'petrol'}, // object prop
showSize: function() {
console.log('single prop: ' + this.engine.size );
console.log('object prop: ' + this.engine.type.size);
}
};
var car = Object.assign(Object.create(vehicle), {
wheels: 4,
drift: function() { console.log('drifting'); }
});
var ferrari = Object.assign(Object.create(car), {
colour:'red',
engine: Object.create(engine)
});
var porsche = Object.assign(Object.create(car), {
colour:'silver',
engine: Object.create(engine)
});
// ferrari owner changes his engine
ferrari.engine.size = '100cc';
ferrari.engine.type.size = '100cc';
console.log('ferrari:');
ferrari.engine.showSize.call(ferrari);
console.log('\nporsche:');
porsche.engine.showSize.call(porsche);
/*
OUTPUT
ferrari:
single prop: 100cc
object prop: 100cc
porsche:
single prop: V12
object prop: 100cc <------ WRONG, should be V12
*/
EDIT : for anyone that stumbles across this, I'm going to use this pattern; it's more intuitive for me to create constructors and use call(this). The irony is that it's very close to Amit's answer, but I feel that function constructors aren't in the true spirit of prototypal inheritance/delegation.
Having to do this in each 'class' seems clunky:
car.prototype = Object.create(vehicle.prototype ); // <- new way
car.prototype = new vehicle(); // <- old way
car.prototype.constructor = car;
Instead, I know exactly what's going on using this pattern:
var car = Object.create(vehicle, {
constructor : { value: function (colour, wheels) {
vehicle.constructor.call(this, colour, wheels);
return this;
}}
});
It's six of one, half a dozen of the other ;)