Lets say I have this:
function Foo(){
this.name = "fooos";
};
Now later in the script I have a reference to Foo
, and what to add properties to Foo when instantiated. I could do something like this:
Foo.prototype.myProp = 3;
foo = new Foo();
expect(foo).to.have.property('name');
expect(foo).to.have.property('myProp');
This works great until I need to attach an object to prototype, like so:
Foo.prototype.myProp = { bar : 3 };
The issue is that now instances will share state on bar
(as `bar is just a reference):
foo = new Foo();
foo2 = new Foo();
foo.myProp.bar = 5;
expect(foo2.myProp.bar).to.equal(5);
Which is not desirable. However if the object is added inside the constructor the instances do not share state.
Is there a way around this? I don't have access to the constructor to manipulate it. I need to attach an object to an instance from the prototype.
Properties don't have to be on prototypes, you can just add them directly to instances:
var f = new Foo();
f.myProp = { bar: 3 };
I know that. Its not what I want.
The only way I can think of to do this via the prototype with a property (not a method; @meager has a solution using a method) is an ugly hack where you define the property on the prototype with Object.defineProperty
(ES5-only) and then redefine it on first access, like this:
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;
}
});
I would not recommend that. :-)
An alternative would be to throw a facade in front of Foo
, like this:
var OriginalFoo = Foo;
Foo = function() {
OriginalFoo.apply(this, arguments);
this.myProp = { bar: 3 };
};
Foo.prototype = Object.create(OriginalFoo.prototype);
That would, of course, only apply to objects created via new Foo
after this code executed.