Geo
Geo

Reputation: 23

javascript why 2 different object are refering to/using same array?

I have an object definition that has an array in it. When I instantiate 2 objects and access its members both object write to the same array. I was expecting for each object to have their own array and not share the same one. It works fine for the other members of the object. Why is this and what is the correct way of doing this? Below is a sample code

//define simple object
var OBJ = {
  id: 0,
  arr: [0,0]
};

//instantiate objects
let obj1 = Object.create(OBJ);
let obj2 = Object.create(OBJ);

//change members value
obj1.id = 1;
obj1.arr[0]=1111;

obj2.id=2;
obj2.arr[1]=2222;

//verify changes
console.log(obj1.id);   //id = 1 as expected
console.log(obj1.arr);  //<--- expected [1111, 0000] NOT [1111, 2222]
console.log(obj2.id);   //id = 2 as expected
console.log(obj2.arr);  //<--- expected [0000, 2222] NOT [1111, 2222]

Upvotes: 0

Views: 76

Answers (3)

Ayan
Ayan

Reputation: 8906

What you are trying to achieve,is possible by :

function OBJ() {
    this.id = 0;
    this.arr = [0,0];
}

let obj1 = new OBJ();    
let obj2 = new OBJ(); 

because it creates a separate instance for each new created object i.e. each new created object has its own copy of id and arr.


Your approach would work fine for primitive data types,but not for non-primitive data types like Array.You are instantiating an array on the prototype without realizing that mutating that array will modify it for all instances.

obj1 and obj2 originally have reference to the same id and arr of the OBJ prototype.

obj1 / obj2 has its own new copy of id only when obj1.id / obj2.id is changed,otherwise they refer to the same id of OBJ's prototype.

Now,this behaviour is only for primitive types. With non-primitive types i.e. Array , both obj1 and obj2 always refer to the same arr of the OBJ prototype.

Upvotes: 1

Ori Drori
Ori Drori

Reputation: 192317

Problem

When you use Object.create() to create an new object from OBJ, OBJ becomes the prototype of the new object. All methods and properties are taken from the prototype chain, unless the object overrides them by having it's own properties with the same name. Since the arr is a property of OBJ, all objects update, and display the same array.

Suggested Solution

You can convert arr to a getter that will check if arr is a property of the current object using Object.hasOwnProperty(), and if not, clone the prototypes array, and then return it.

//define simple object
var OBJ = {
  id: 0,
  _arr: [0, 0],
  get arr() {
    if(!this.hasOwnProperty('_arr')) this._arr = [...this._arr];
    
    return this._arr;
  }
};

//instantiate objects
let obj1 = Object.create(OBJ);
let obj2 = Object.create(OBJ);

//change members value
obj1.id = 1;
obj1.arr[0] = 1111;

obj2.id = 2;
obj2.arr[1] = 2222;

//verify changes
console.log(obj1.id); //id = 1 as expected
console.log(obj1.arr); //<--- expected [1111, 0000]

console.log(obj2.id); //id = 2 as expected
console.log(obj2.arr); //<--- expected [0000, 2222]

Upvotes: 0

Guichi
Guichi

Reputation: 2343

https://lodash.com/docs/4.17.5#cloneDeep

should be what you want, it will copy everything recursively

Upvotes: 0

Related Questions