I'm attempting to have a main object that I can create multiple instances of, that each inherit the children (with unique/isolated properties). When I do this, however, the properties of the object (after being changed) are changing for all created objects. I may not be explaining this correctly, but the example should be pretty clear.
Main = function(){};
// Extending the main class with new object. Doing it this way so I can have these in
// separate files.
Main.prototype.foo = {
bar: 1
}
// First instance of Main().
var A = new Main();
// Second instance of Main().
var B = new Main();
// Set the bar property to different values for each Main() object.
A.foo.bar = 2;
B.foo.bar = 3;
// Both A.foo.bar and B.foo.bar return 3.
alert(A.foo.bar);
alert(B.foo.bar);
What I'm trying to get to have happen, is for A.foo.bar to return 2 and B.foo.bar to return 3, so that I have isolated objects that are independent of each other.
Any ideas? Am I just missing something that's obvious? Would be much appreciated!
The "foo" property is on the prototype object, and there's only one of those. When you set it via any instance, you're affecting that same shared property.
You can add an instance property in your constructor:
function Main() {
this.instanceProperty = 1;
}
Then that'll be per-instance.
The prototype is not a "master template" or anything like that; it's a real object. It's not copied onto instances. Instead, the runtime knows it's there, and when references are made to properties on an instance that don't actually exist on the instance, then it knows to walk up the prototype chain and look for properties there.
The other answers are more or less correct, but what they're missing is that there's a difference between
Main.prototype.foo = {
bar: 1
};
and
Main.prototype.bar = 1;
In both cases, instantiating a new Main
will create a new instance with, in its prototype chain, a property foo
or bar
. In both cases, the instance-level property can be redefined without affecting other instances:
function Main() {};
Main.prototype.foo = {
bar: 1
};
Main.prototype.bar = 1;
a = new Main();
b = new Main();
a.foo = { bar: 2 };
console.log(a.foo.bar, b.foo.bar); // 2 1
a.bar = 2;
console.log(a.bar, b.bar); // 2 1
But when you instantiate a new Main
, the instance variable foo
is a reference to a single object, {bar:1}
, which is shared among all instances. So when you set a.foo.bar
, you're changing the common object, not an instance variable; the instance variable is the reference a.foo
.
You don't have to initialize the instance property in the constructor. The standard approach would be to set bar
directly on the prototype, i.e. Main.prototype.bar = 1
, which would give you independent instance variables initialized to 1
. However, if you need a more complex data structure (an object, an array, or an instance of another class) on a per-instance basis, then you can't create this as a property on the prototype, because you'll be giving every instance a reference to a common object - so inside the constructor is the way to go:
function Main() {
// instance-level object
this.foo = {
bar: 1
};
}
Since you're editing something on the prototype, it's going to affect every object.
However, you can do:
A.x = 2;
B.x = 3;
Then you'll have different results.
Or, you can have something like this:
Main = function(val){
this.x = val;
}
A = new Main(2);
B = new Main(3);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With