Javascript prototype inheritance - shared property

I saved the _data property in the prototype as a definition for all created objects.

  function A() {} A.prototype._data = []; 

Now all objects created from A have the _data property.

I would like to inherit a prototype where the prototype _data will have _data values ​​from all prototypes in the prototype chain.

I don’t know the direct path, in this example I use 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 an object A with values aa and an object b with value bb , b.get() returns [aa, bb] . And later, if prototype A _data is expanded using aaaa , the b.get() function will return [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] 

This is 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/

The reason for all this is to define a field for the schema in the ORM library, where schema inheritance is allowed. The child schema must have all the fields from the parent schema.

+6
source share
3 answers

I would like to inherit a prototype where the prototype _data will have _data values ​​from all prototypes in the prototype chain.

This is another matter. “Prototype inheritance” means that if the _data property is on the current object, it will not look further in the chain. Also, this seems like a problem with nested objects , although I'm not sure what you really want. However, it hardly makes sense to allow an array object to inherit from another array if you really want to concatenate it.

So, I think your getter is really beautiful.

This is a good (standard) way, how to achieve this? I mean using constructor correction, while Object.create and the parent prototype reference with the .prototype constructor

The constructor corrector is good, but actually useless (especially if you expect a standard Object.create ).

However, in this.__proto__.constructor.prototype either .__proto__ or .constructor.prototype is redundant. Since both of them are either non-standard or require constructor correction, you must use the standard Object.getPrototypeOf() function to get your object prototype.

Using the following very general solution, you can nest inheritance (A.proto, B-proto, B-instance, ...) arbitrarily deep. Everyone inheriting from A.prototype will have an add method that 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 

Usage example:

 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] 
+1
source
  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

+1
source

I think I have a better understanding of what you want to do now, so I deleted my previous answer and posted it.

This is how I think I will do it (with the warning that I'm not at all sure that with an even better understanding, a completely different approach would not be better):

 function A() {} A.prototype._Adata = []; A.prototype.add = function(rec) { this._Adata.push(rec); }; A.prototype.get = function() { return this._Adata; }; function B() {} B.prototype = Object.create(A.prototype, { constructor: { value: B }}); B.prototype._Bdata = []; B.prototype.add = function(rec) { this._Bdata.push(rec); }; B.prototype.get = function() { return this._Adata.concat(this._Bdata); // Or: return A.prototype.get.call(this).concat(this._Bdata); }; var a = new A(); var 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] 

Fiddle

Thus, B does not penetrate too deeply into the internal elements of A

+1
source

All Articles