JavaScript 原型共享属性

javascript prototype shared property

本文关键字:属性 共享 原型 JavaScript      更新时间:2023-09-26

我已经在原型中保存了一个属性_data作为所有已创建对象的定义。

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

现在,从A创建的所有对象都具有属性_data

我想要原型继承,其中原型_data将具有原型链中所有原型的_data值。

不知道直接的方式,在这个例子中我使用一个 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 = [];

当我使用值aa创建对象a并使用值bb创建对象b时,b.get()返回[aa, bb]。稍后如果原型A_data将用aaaa扩展,函数b.get()返回[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]

如何实现这一目标是一种好的(标准(方法吗?我的意思是在Object.create时使用构造函数校正并使用constructor.prototype引用父原型?

这是一个演示:http://jsfiddle.net/j9fKP/

所有这些原因是ORM库中方案的字段定义,其中允许方案的继承。子方案必须具有父方案中的所有字段。

我想要原型继承,其中原型_data将具有原型链中所有原型的_data值。

那是另一回事。"原型继承"意味着如果当前对象上有 _data 属性,它将不会在链中进一步查找。此外,这似乎是嵌套对象的一种问题,尽管我不确定您真正想要什么。但是,如果您实际上想要连接数组对象,那么让数组对象从另一个数组继承几乎没有意义。

所以我认为你的吸气剂真的很好。

如何实现这一目标是一种好的(标准(方法吗?我的意思是使用构造函数校正,而 Object.create 并使用 constructor.prototype 引用父原型

构造函数更正很好,但实际上毫无用处(特别是如果您期望符合标准的Object.create(。

但是,在this.__proto__.constructor.prototype .__proto__.constructor.prototype都是多余的。由于两者都是非标准的或需要构造函数更正,因此应使用标准Object.getPrototypeOf()函数来获取原型对象。

使用以下非常通用的解决方案,您可以任意深度嵌套继承(A.proto,B-proto,B-instance等(。从A.prototype继承的所有内容都将有一个add方法,该方法将_data添加到当前对象,以及一个遍历原型链并收集所有_dataget方法:

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

用法示例:

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]

小提琴

我想

我对你现在想做什么有了更好的理解,所以我删除了我之前的答案并发布了这个答案。

以下是我认为我会如何做到这一点(需要注意的是,我完全不确定,有了更好的理解,完全不同的方法不会更好(:

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]

小提琴

这样,B就不会太深入A的内部。