Yoav Kadosh
Yoav Kadosh

Reputation: 5155

Instantiating a New Object References The Same Property

Why when I instantiate a new object in JavaScript that has another object as one of its properties, does it always reference the same object?

For example

function test() {}

test.prototype.state = {
    num: 0
};

var obj1 = new test();
var obj2 = new test();

obj1.state.num = 1;

console.log(obj1.state.num,obj2.state.num); // Outputs 1 1 instead of 1 0

Also, what would be the appropriate way to make it create a new object property every time it is instantiated?

Upvotes: 0

Views: 82

Answers (3)

Redu
Redu

Reputation: 26161

I would like to explain in the following code.

function test() {
  var o = {a:1};
  this.geto = function(){return o.a};
  this.seto = function(v){o.a = v};
}

test.prototype.p = {a:0};

var obj1 = new test();
var obj2 = new test();

obj1.p.a = 100;
obj1.seto(50);
console.log(obj1.p.a);    // <- 100
console.log(obj2.p.a);    // <- 100
console.log(obj2.geto()); // <- 1
console.log(obj1.geto()); // <- 50

In the first code there is a closure and it is not shared. All instantiated objects have a separate closure. In the prototype version there is no closure and all instantiated objects access the very same object at the prototype of the constructor.

There is also a more complicated prototypical sharing of closures exist and that i had explained here in which we share the closure itself through the prototype.

Upvotes: 0

Alex Kudryashev
Alex Kudryashev

Reputation: 9470

In your code .status.num appear to belong to the class, not instance. Change your code to something like this:

function test() {
  this.state = {num:0};//instance property
}
var obj1 = new test();
var obj2 = new test();

obj1.state.num = 1;

console.log(obj1.state.num,obj2.state.num);//1 0 as expected

Upvotes: 0

deceze
deceze

Reputation: 522110

Because that's what the prototype is: a shared object among all instances. You're explicitly creating the { num: 0 } object only once, so it will exist only once. Javascript doesn't clone it for you when instantiating a new test. Usually the prototype is used for functions, where this doesn't make any difference. If you want instance specific attributes, you need to create them in the constructor function:

function test() {
    this.state = { num: 0 };
}

Upvotes: 2

Related Questions