I get an unexpected result with the following code:
var TestModel, u, u2;
function TestModel() {}
TestModel.prototype.a = null;
TestModel.prototype.b = [];
u = new TestModel();
u.a = 1;
u.b.push(1);
u2 = new TestModel();
u2.a = 2;
u2.b.push(2);
console.log(u.a, u.b); // outputs: 1 [1,2]
console.log(u2.a, u2.b); // outputs: 2 [1,2]
I find it surprising that u.b
and u2.b
contain the same values even though each instance of TestModel
should have its own instance variables according to how I've setup the prototype. So this is the output I was expecting:
console.log(u.a, u.b); // expecting: 1 [1]
console.log(u2.a, u2.b); // expecting: 2 [2]
The same thing happens if I set b
to be an object and set keys on it rather than using it as an array. What am I not understanding here?
I get an unexpected result with the following code:
var TestModel, u, u2;
function TestModel() {}
TestModel.prototype.a = null;
TestModel.prototype.b = [];
u = new TestModel();
u.a = 1;
u.b.push(1);
u2 = new TestModel();
u2.a = 2;
u2.b.push(2);
console.log(u.a, u.b); // outputs: 1 [1,2]
console.log(u2.a, u2.b); // outputs: 2 [1,2]
I find it surprising that u.b
and u2.b
contain the same values even though each instance of TestModel
should have its own instance variables according to how I've setup the prototype. So this is the output I was expecting:
console.log(u.a, u.b); // expecting: 1 [1]
console.log(u2.a, u2.b); // expecting: 2 [2]
The same thing happens if I set b
to be an object and set keys on it rather than using it as an array. What am I not understanding here?
3 Answers
Reset to default 13There is a difference between assigning values and referencing them.
u.a = 1;
will create a new a
property on the object referred to by u
. Before the assignment, u.a
will refer to TestModel.prototype.a
, but assigning a new value actually creates a new property on the actual object:
After the assignment:
On the other hand,
u.b.push(1);
will not create a new property. It will reference the existing property, the array, which is TestModel.prototype.b
.
even though each instance of
TestModel
should have its own instance variables according to how I've setup the prototype
All instances reference the same prototype, hence they reference the same properties the prototype has. You can easily see that because TestMode.prototype === u.b
, TestMode.prototype === u2.b
and u.b === u2.b
all yield true
.
It would work if you assign a new value as well to u.b
and u2.b
as well:
u.b = [];
which is normally done in the constructor:
function TestModel() {
this.b = [];
}
Prototype properties are exactly the opposite of each instance having their own variables, the point of prototype is that all instances automatically share the same prototype properties, so redefining functions is not required for each instance.
You want each instance to have their own array like this:
function TestModel() {
this.a = null;
this.b = [];
}
The array is in both cases the very same array, namely the one you set to the prototype. This means that both .push
calls are acting on that array, so that all of these are [1, 2]
:
TestModel.prototype.b
u.b
u2.b
They all refer to the same property.
Prototype is usually used for functions, so that all instances share those same functions. If you are going to modify prototype properties, then they will also be reflected for all instances, which in this case is probably undesirable. If instances should each have a custom array, then also declare a custom one for each instance instead of via prototype.