让我说我有这个:
function Foo(){
this.name = "fooos";
};
现在稍后在脚本中我引用了Foo
,以及在实例化时向Foo添加属性的内容。我可以这样做:
Foo.prototype.myProp = 3;
foo = new Foo();
expect(foo).to.have.property('name');
expect(foo).to.have.property('myProp');
这很有用,直到我需要将一个对象附加到原型上,如下所示:
Foo.prototype.myProp = { bar : 3 };
问题是现在实例将在bar
上共享状态(因为`bar只是一个参考):
foo = new Foo();
foo2 = new Foo();
foo.myProp.bar = 5;
expect(foo2.myProp.bar).to.equal(5);
哪个不可取。但是,如果在构造函数中添加了对象,则实例不会共享状态。
有解决方法吗?我无权访问构造函数来操作它。我需要将一个对象附加到原型中的实例。
答案 0 :(得分:6)
属性不必在原型上,您只需将它们直接添加到实例:
var f = new Foo();
f.myProp = { bar: 3 };
我知道。这不是我想要的。
我能想到通过原型使用属性(不是方法; @meager使用方法a solution)来实现这一目标的唯一方法是丑陋的黑客攻击在原型上使用Object.defineProperty
(仅限ES5)定义属性,然后在首次访问时重新定义,如下所示:
Object.defineProperty(Foo.prototype, "myProp", {
get: function() {
var obj = { bar: 3 };
Object.defineProperty(this, "myProp", {
get: function() {
return obj;
},
set: function(value) {
obj = value;
}
});
return obj;
}
});
我会 不 推荐。 : - )
另一种方法是在Foo
前面放置一个外观,如下所示:
var OriginalFoo = Foo;
Foo = function() {
OriginalFoo.apply(this, arguments);
this.myProp = { bar: 3 };
};
Foo.prototype = Object.create(OriginalFoo.prototype);
当然,这只会在执行此代码后才适用于通过new Foo
创建的对象。
答案 1 :(得分:2)
根据您对需要完成原型的限制,您无法执行此操作。原型是共享的,你不能通过原型给每个实例一个唯一的对象。通过定义原型是非常不可能的。
最接近的是添加一个访问器方法,该方法将该属性延迟添加到特定实例,但这与您的问题相去甚远:
Foo.prototype.getMyProp = function () {
this.myProp = this.myProp || { bar: 3; }
return this.myProp
}
foo = new Foo();
foo2 = new Foo();
foo.getMyProp().bar = 5
expect(foo2.getMyProp().bar).to.equal(3);