Reputation: 1250
I don't understand why this behavior is happening. Lets say I define an object and make an array of 3 of this object. If I modify the objects in the array, it affects all instances of the object? Could someone explain why this is? Also, how do I make an array with independent "Copies" of the object to get the desired behavior? Thanks!
example
testObject = {"value1":"a","value2":"b"};
objArray = [];
for(i=0; i < 3; i++){
var newobj = testObject; //make a new testObject
objArray.push(newobj); //push new object to array
}
delete objArray[0].value2 // Desired, delete value 2 ONLY from array object 0
objArray[2].value2 //Undefined? Why is value2 missing from object 2
testObject.value2 //Undefined? Why is value2 missing from original object?
Upvotes: 0
Views: 160
Reputation: 14434
As opposed to primitives (strings, numbers, booleans, symbols null, undefined), objects in javascript are passed by reference
. Variables serve as placeholders/pointers to these objects. To create a copy of an object without the risk of mutation you'd use spread (barring compatibility):
const newObject = { ...testObject };
or traditionally, Object.assign(), passing an empty object literal to avoid mutability of the original testObject
:
const newObject = Object.assign({}, testObject);
As far as deep cloning, MDN suggests using a combination of JSON.parse()
and JSON.stringify()
. So for example:
const testObject = { value: "a", other: { value2: b } };
const newObject = JSON.parse(JSON.stringify(testObject));
Upvotes: 2
Reputation: 191749
When creating an Object in JavaScript, you are actually creating a reference to that object. You can store this in a variable and pass it around ... perhaps append it to an array. When you go to do operations on an object reference, it finds the original object that the reference points to and updates it. Thus when you use .push
it's not creating a new object but simply pushing the reference to that object. If you update it in one spot it will update it in the other and any others where you have assigned that reference.
Copying an object into a new object is generally called cloning. There are a lot of different ways to clone objects in JavaScript with varying results.
You can use var newobj = { ...testObject }
as the other answer suggests. This spread operator essentially copies the properties of testObject
and creates a new object (declared with the outer {
}
). The reference to that new object is then assigned to newobj
. You can think of it as doing this:
var newobj = {
value1: testObject.value1,
value2: testObject.value2,
};
However, you should keep in mind that this gives you only one level of cloning. That is to say if your object contains other objects then the reference to that object will be assigned as the property rather than a clone of that object. For example: let's say you had:
var testObject = { obj: { a: "b" } };
var newobj = { ...testObject };
delete testObject.obj.a;
console.log(newobj); // { obj: {} }
In order to solve this, you need to do what is called a deep clone which in JavaScript can be done by recursively cloning object properties that are also objects. There are a bunch of ways to do this including libraries like lodash
or home-grown functions. One example on SO: What is the most efficient way to deep clone an object in JavaScript?
Finally, if testObject
is supposed to be something like an object template or initial state from which other newobj
are derived, it might make more sense to use a function:
function newObjFactory() {
return {
value1: "a",
value2: "b",
};
}
Then you can do var newobj = newObjFactory()
and you'll get a new object each time since a new object is created by the function each time it's called and return
ed.
Upvotes: 0
Reputation: 1456
You are pushing same object's reference again and again in the loop.
for(i=0; i < 3; i++){
var newobj = testObject; //no new object,same object's reference again
objArray.push(newobj); //push new object to array
}
It should be
for(i=0; i < 3; i++){
var newobj = {"value1":"a","value2":"b"}; //make a new testObject
objArray.push(newobj); //push new object to array
}
Upvotes: 0