I have saved a property _data
in prototype as a definition for all created objects.
function A() {}
A.prototype._data = [];
Now all objects created from A
have property _data
.
I'd like prototype inheritance, where _data
of prototype will have _data
values from all prototypes in prototype chain.
Don't know direct way, in this example I use a getter get()
.
function A() {}
A.prototype._data = [];
A.prototype.add = function(rec) {
this.__proto__._data.push(rec);
}
A.prototype.get = function() {
if(typeof this.__proto__.constructor.prototype.get == 'function')
{
return this.__proto__.constructor.prototype.get().concat(this.__proto__._data);
}
else
{
return this.__proto__._data || [];
}
}
function B() {}
B.prototype = Object.create(A.prototype, { constructor: { value: B }});
B.prototype._data = [];
When I create object a
with values aa
and object b
with value bb
, b.get()
returns [aa, bb]
. And later if _data
of prototype A
will be extended with aaaa
, function b.get()
returns [aa, aaaa, bb]
.
var a = new A(), b = new B();
a.add('aa');
b.add('bb');
console.log(b.get()); // [aa, bb]
a.add('aaaa');
console.log(b.get()); // [aa, aaaa, bb]
// EDITED - _data in A prototype shoud be without B
console.log(a.get()); // [aa, aaaa]
Is it a good (standard) way how to achieve this? I mean using constructor correction while Object.create
and reference parent prototype with constructor.prototype
?
Here is a demo: http://jsfiddle.net/j9fKP/
Reason for all of this is field definition for scheme in ORM library, where inheritance of schemes is allowed. Child scheme has to have all fields from parent scheme.
I'd like prototype inheritance, where
_data
of prototype will have_data
values from all prototypes in prototype chain.
That's a different thing. "Prototype inheritance" means that if there's a _data
property on the current object, it won't go looking further in the chain. Also, it seems to be a kind of issue with nested objects, though I'm not sure what you really want. However, it hardly will make sense to let an array object inherit from another array, if you actually want to concatenate them.
So I think your getter is really fine.
Is it a good (standard) way how to achieve this? I mean using constructor correction while Object.create and reference parent prototype with constructor.prototype
Constructor correction is nice, but actually quite useless (especially if you expect a standard-conform Object.create
).
However, in this.__proto__.constructor.prototype
either the .__proto__
or the .constructor.prototype
is redundant. Since both are either nonstandard or require constructor correction, you should use the standard Object.getPrototypeOf()
function to get your prototype object.
With the following very generic solution, you can nest the inheritance (A.proto, B-proto, B-instance, …) arbitrarily deep. Everything inheriting from A.prototype
will have an add
method which adds _data
to the current object, and a get
method that traverses the prototype chain and collects all _data
:
function A() {
// this._data = []; // why not?
}
A.prototype._data = []; // not even explicitly needed
A.prototype.add = function(rec) {
if (! this.hasOwnProperty("_data")) // add it to _this_ object
this._data = [];
this._data.push(rec);
}
A.prototype.addToAllInstances = function(rec) {
Object.getPrototypeOf(this).add(rec);
}
A.prototype.get = function() {
var proto = Object.getPrototypeOf(this);
var base = typeof proto.get == 'function' ? proto.get() : [];
// maybe better:
// var base = typeof proto.get == 'function' && Array.isArray(base = proto.get()) ? base : [];
if (this.hasOwnProperty("_data"))
return base.concat(this._data); // always get a copy
else
return base;
}
function B() {
A.call(this);
}
B.prototype = Object.create(A.prototype, { constructor: { value: B }});
B.prototype._data = []; // not even explicitly needed
Example usage:
var a = new A();
var b = new B();
a.add('ai');
a.get(); // [ai]
a.addToAllInstances('ap'); // === A.prototype.add('ap');
a.get(); // [ap, ai]
new A().get(); // [ap]
b.get(); // [ap]
b.prototype.get(); // [ap]
b.add('bi');
b.get(); // [ap, bi]
a.addToAllInstances('aap');
b.addToAllInstances('bp');
b.get(); // [ap, aap, bp, bi]
function A() {}
A.prototype._data = [];
A.prototype.add = function(rec) {
this._data.push(rec);
}
A.prototype.get = function() {
return this._data;
}
function B() {}
B.prototype = Object.create(A.prototype, { constructor: { value: B }});
B.prototype._data = [];
B.prototype.get = function() {
return A.prototype._data.concat(this._data);
}
a.add('aa');
b.add('bb');
console.log(b.get()); // [aa, bb]
a.add('aaaa');
console.log(b.get()); // [aa, aaaa, bb]
Fiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With