javascript原型继承 - 共享属性

时间:2013-03-16 13:26:25

标签: javascript inheritance prototype

我在原型中保存了一个属性_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 = [];

当我创建值a的对象aa和值b的对象bb时,b.get()会返回[aa, bb]。稍后如果原型_data的{​​{1}}将使用A进行扩展,则函数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引用父原型?

以下是演示:http://jsfiddle.net/j9fKP/

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

3 个答案:

答案 0 :(得分:1)

  

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

这是另一回事。 “原型继承”意味着如果当前对象上有_data属性,它将不会在链中进一步查看。此外,它似乎是一种issue with nested objects,虽然我不确定你真正想要的是什么。但是,如果你真的想要连接它们,那么让一个数组对象继承另一个数组几乎没有意义。

所以我觉得你的吸气得很好。

  

如何实现这一目标是一种很好的(标准)方式吗?我的意思是使用构造函数更正Object.create和引用父原型与constructor.prototype

构造函数更正很好,但是actually quite useless(特别是如果你期望符合标准的Object.create)。

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

使用以下非常通用的解决方案,您可以任意深入地嵌套继承(A.proto,B-proto,B-instance,...)。从A.prototype继承的所有内容都将使用add方法将_data添加到当前对象,并使用get方法遍历原型链并收集所有_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

使用示例:

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 :(得分:1)

 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

答案 2 :(得分:1)

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

以下是我认为我会这样做的原因(但有一点需要注意,我不能确定更好的理解,完全不同的方法会更好):< / p>

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

这样,B并没有深入到A的内部。

相关问题