javascript原型继承-共享属性
Posted
技术标签:
【中文标题】javascript原型继承-共享属性【英文标题】:javascript prototype inheritance - shared property 【发布时间】:2013-03-05 04:43:02 【问题描述】:我在原型中保存了一个属性_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]
。之后,如果原型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 库中方案的字段定义,其中允许方案的继承。子方案必须具有父方案的所有字段。
【问题讨论】:
javascript object members that are prototyped as arrays become shared by all class instances的可能重复 【参考方案1】:我想要原型继承,其中原型的
_data
将具有来自原型链中所有原型的_data
值。
那是另一回事。 “原型继承”意味着如果当前对象上有一个_data
属性,它就不会在链中进一步查找。此外,它似乎是一种issue with nested objects,虽然我不确定你真正想要什么。但是,如果您真的想连接它们,让一个数组对象从另一个数组继承几乎没有意义。
所以我认为你的吸气剂真的很好。
这是一个很好的(标准)方法来实现这一点吗?我的意思是在 Object.create 和使用 constructor.prototype 引用父原型时使用构造函数更正
构造函数更正很好,但actually quite useless(特别是如果您期望符合标准的Object.create
)。
但是,在 this.__proto__.constructor.prototype
中,.__proto__
或 .constructor.prototype
是多余的。由于两者都是非标准的或 require 构造函数更正,您应该使用标准的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]
【讨论】:
非常好的代码!使用 getPrototypeOf 并且还忘记了实例 _data 属性。非常感谢您的出色解释和示例。正是我需要的。【参考方案2】: 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
【讨论】:
我很抱歉我最近编辑的问题很糟糕,a.get() 应该只返回 [aa, aaaa]。谢谢【参考方案3】:我想我对你现在想要做什么有了更好的理解,所以我删除了我之前的答案并发布了这个。
我认为我会这样做(需要注意的是,我完全不确定如果更好理解,完全不同的方法不会更好):
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
的内部。
【讨论】:
_Adata
不是“内部人员”吗?您可以(并且 imo 应该)使用 A 的 get
。
@Bergi:是的,我想你可能会说它是。对我来说,这些的全部意义在于分享这些信息,所以我不认为它们是“内部的”,如果没有帮助库,调用A
的get
版本会很痛苦。但我已将其添加为选项。以上是关于javascript原型继承-共享属性的主要内容,如果未能解决你的问题,请参考以下文章