Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript prototype property not working as expected with array and object fields

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?

like image 803
hiddentao Avatar asked Nov 22 '11 16:11

hiddentao


People also ask

Is __ proto __ deprecated?

prototype. __proto__ Deprecated: This feature is no longer recommended.

What is difference between __ proto __ and prototype?

prototype is a property of a Function object. It is the prototype of objects constructed by that function. __proto__ is an internal property of an object, pointing to its prototype. Current standards provide an equivalent Object.

Do all JavaScript objects have a prototype property?

Each and every JavaScript function will have a prototype property which is of the object type. You can define your own properties under prototype . When you will use the function as a constructor function, all the instances of it will inherit properties from the prototype object.

How do you check if an object has a specific property in JavaScript?

Object.prototype.hasOwnProperty() The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).


1 Answers

There 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:

enter image description here

After the assignment:

enter image description here

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 = [];
}
like image 146
Felix Kling Avatar answered Sep 19 '22 06:09

Felix Kling