Reputation: 1898
Plunker - http://plnkr.co/edit/9tRSsBw2upSmXbF83D90 (code also at the end of this post )
I have a prototype function (generic) and another function which extends this prototype (specific). In the generic prototype I have a data object. I want the specific object to use this data object as a basis for it's own prototype data object data and to add keys to this data object instead of creating a new data object (which is what I think it's doing).
Plunker should illustrate what I mean.
Can someone tell me what prototype magic I'm missing to make specific also check the properties of the data ancestor instead of (as it seems to do) creating a new data object in its own prototype?
<script>
function genericDataObject ( dataObject ) {
if( !dataObject ) {
this.data = {};
} else {
this.loadDataObject(dataObject);
}
}
genericDataObject.prototype = {
//want all data objects to have the alwayshere property
data: {alwayshere: null},
loadDataObject: function (dataObject) {
//if our dataObject has a key that is set to null in data then replace null with that key's value
for (var key in dataObject) {
if( this.data[key] === null) {
this.data[key] = dataObject[key];
}
}
}
}
function specificDataObject ( dataObject ) {
genericDataObject.call(this, dataObject );
}
specificDataObject.prototype = new genericDataObject();
//add specific properties, shouldn't data be instantiated here with alwayshere as we've called new genericDataObject()????
specificDataObject.prototype.data.specificData1 = null;
specificDataObject.prototype.data.specificData2 = null;
var genericObject = new genericDataObject( { alwayshere: "here it is"} );
var specificObject = new specificDataObject( {alwayshere: "where is it?", specificData1: "this works"});
document.write( genericObject.data.alwayshere + "<br />"); //"here it is"
document.write( specificObject.data.alwayshere + "<br />" );// undefined
document.write( specificObject.data.specificData1);// "this works"
</script>
Upvotes: 0
Views: 115
Reputation: 664196
You will need to create a new data
object for each instance, otherwise all instances will share the same object (which is inherited to all from the prototype), and modifications to this object will affect all instances.
You've got a very messed up relations between your objects:
genericObject: {} // empty!!!
- inherits .data (and other properties) from genericDataObject.prototype
specificObject: {} // empty!!!
- inherits .data (and other properties) from specificDataObject.prototype
genericDataObject.prototype: {data:…, loadDataObject:…}
- inherits from Object.prototype
genericDataObject.prototype.data: {alwayshere: "here it is"}
- inherits from Object.prototype
- created as {alwayshere: null} in prototype literal
- assigned "here it is" in genericObject.loadDataObject(…) //!!!
specificDataObject.prototype: {data:…}
- inherits from genericDataObject.prototype
- created by `new genericDataObject();`
specificDataObject.prototype.data:{specificData1:"this works",specificData2:null}
- inherits from Object.prototype //!!!
- created as {} in the genericDataObject constructor
- assigned specificData1:null, specificData2:null explicitly
- did *not* assign alwayshere:"where is it?" in specificObject.loadDataObject(…)
because .alwayshere was not `null` - the property does not exists //!!!
- did assign specificData1:"this works" in specificObject.loadDataObject(…)//!!!
As you can see, there are only two data
objects which somehow have accumulated all the properties. And the one does not inherit from the other - only the two .prototype
objects do have a prototype relationship. This is not what you want.
Instead, you should do:
function genericDataObject ( dataObject ) {
this.data = Object.create(this.data);
if (dataObject) {
this.loadDataObject(dataObject);
}
}
genericDataObject.prototype.data = {alwayshere: null};
genericDataObject.prototype.loadDataObject = function (dataObject) {
// *only* if our dataObject has a key that is set to null in data then replace null with that key's value
for (var key in dataObject) {
if( this.data[key] === null) {
this.data[key] = dataObject[key];
}
}
};
function specificDataObject(dataObject) {
genericDataObject.call(this, dataObject);
}
specificDataObject.prototype = Object.create(genericDataObject.prototype);
specificDataObject.prototype.data = Object.create(genericDataObject.prototype.data);
specificDataObject.prototype.data.specificData1 = null;
specificDataObject.prototype.data.specificData2 = null;
Upvotes: 1