0

const obj1 = { a: 0, b: { c: 0 } };
const obj2 = Object.assign({}, obj1);
console.log(obj2); // { a: 0, b: { c: 0 } }

obj1.a = 1;
console.log(obj1); // { a: 1, b: { c: 0 } }
console.log(obj2); // { a: 0, b: { c: 0 } }

obj2.a = 2;
console.log(obj1); // { a: 1, b: { c: 0 } }
console.log(obj2); // { a: 2, b: { c: 0 } }

obj2.b.c = 3;
console.log(obj1); // { a: 1, b: { c: 3 } }
console.log(obj2); // { a: 2, b: { c: 3 } }


I was reading in the MDN documentation about Object.assign() method , then some lines of code stopped me (specifically starting from obj2.b.c = 3) . I don't understand how changing the c value in obj2 affected obj1 . Even though the values of the two (a) properties changed individually in each object before, and none of the two values affected the other . What do I not understand about the nested Object (b) ?

I would be thankful for any answers or references for articles that explains the problem and the solution deeply

Mohammed
  • 45
  • 6
  • "What do I not understand about the nested Object (b) " - what does that mean? How should we know what you don't understand? Do you have any **specific** question about this code? – Nico Haase Feb 17 '23 at 14:59
  • 1
    You don’t understand that it’s the same object—assign is shallow. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#warning_for_deep_clone – Dave Newton Feb 17 '23 at 15:01
  • How did changing a property value in the nested object (b) affect both obj1 and obj2 and on changing the property (a) value in both obj1 and obj2 didn't affect each other ? (property a in obj1 is 1 and property a in obj2 is 2, while on updating the value of property c in one object , it's value also changed in the other one). – Mohammed Feb 17 '23 at 15:02
  • 2
    Object.assign does not make a copy of nested objects. obj1.b points to an object in memory, and ojb2.b points to the *same* object in memory. If you mutate the object, that change is visible no matter which way you access it – Nicholas Tower Feb 17 '23 at 15:02
  • Consider using the browser API [`structuredClone`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone)? – evolutionxbox Feb 17 '23 at 15:03

3 Answers3

1

Object.assign does not create a new object entirely. Instead it just creates a new reference to same memory location which is known as shallow copy. So that's why even if we are changing obj2 it changes obj1 as they are all pointing to same memory location.

If a new object had been created it would be known as deep copy. Go through this article to read more about it. https://flaviocopes.com/how-to-clone-javascript-object

vikash
  • 9
  • 3
1

As you may read in Object.assign page:

For deep cloning, we need to use alternatives, because Object.assign() copies property values.

If the source value is a reference to an object, it only copies the reference value.

For more, read about Deep copy and Shallow copy.


In your example:

const obj1 = { a: 0, b: { c: 0 } };
const obj2 = Object.assign({}, obj1);

obj2 has a shallow copy of obj1, which means it has a copy of the values that are in the first level (a) and a reference to the object that's in b.

If you change obj2.a, you would change the value in the copy.

But when you do obj2.b you are using the reference of the object in obj1 that had {c: 0}.

That's why when you change obj2.b you are referring to that same object (c) which was referred in obj1. They both point to the same memory address.


If you want to do a deep copy you can use JSON.parse(JSON.stringify(OBJ)) which basically will create a string from your object, then it passes it to JSON.stringif which will return a new object (with new references).

You may also have a look at: What is the most efficient way to deep clone an object in JavaScript?

Fcmam5
  • 4,888
  • 1
  • 16
  • 33
0

There's a browser API called structuredClone which may be what you're looking for:

const obj1 = { a: 0, b: { c: 0 } };
const obj2 = structuredClone(obj1);
console.log(obj2); // { a: 0, b: { c: 0 } }

obj1.a = 1;
console.log(obj1); // { a: 1, b: { c: 0 } }
console.log(obj2); // { a: 0, b: { c: 0 } }

obj2.a = 2;
console.log(obj1); // { a: 1, b: { c: 0 } }
console.log(obj2); // { a: 2, b: { c: 0 } }

obj2.b.c = 3;
console.log(obj1); // { a: 1, b: { c: 0 } }
console.log(obj2); // { a: 2, b: { c: 3 } }
evolutionxbox
  • 3,932
  • 6
  • 34
  • 51