javascript – What is the difference between Shallow Copy and Deep Copy?

Question:

Throughout learning Javascript, I have read terminologies such as Shallow Copy and Deep Copy , and the following question arose:

What is the real difference between Shallow Copy and Deep Copy ?

 const moderador = { nombre : "Gbianchi", lenguajesFavoritos : ["JavaScript", "Java","PHP"], esDesarrollador : true, fechaNacimiento : "2010/01/01" } const persona = Object.assign({}, moderador); persona.nombre = "PabloLozano" persona.esDesarrollador = false; persona.lenguajesFavoritos.push("PHP7"); console.info("moderador", moderador ); console.info("persona", persona)

Answer:

If you represent an object as a graph, you will have a tree where in each node you have a property of that object. These properties in turn can be objects, so the depth of the tree grows.

Let's start with a simple object:

const obj1 = {
  A: 1
  B: 2
}

It has two properties that store primitive values, so if we were to copy the object to another:

const obj2 = {
  A : obj1.A,
  B : obj1.B
}

We would have "cloned" the object and we would not have to worry about anything, since the primitive values ​​are immutable.

But what if obj1 is owned by an object? Or if this property has other properties that are objects ?:

const obj1 = {
  A: 1,
  B: { deep: [0,1,2] }
};

const obj2 = {
  A : obj1.A,
  B : obj1.B
};

obj2.B.deep[0] = 3;

¡Estaríamos modificando el objeto obj1!

This is considered a shallow copy, because we do not replicate each of the saved values ​​recursively: we have stopped at the first level of depth.

The danger of the "shallow" copy is to find ourselves with this type of collateral effects when modifying properties of an object, while we think that another object is totally independent of what we are doing.

But doing a deep copy can be:

  • Expensive : if the depth of the object to be copied is large.
  • Complex : if we do not really have a tree, but a graph with cycles. In this case, an algorithm that is poorly designed or that does not expect this structure can end up in an infinite loop or in a stack overflow due to excessive recursion. Also, some of the properties can be functions (methods) that might behave strangely when changing the context (this).

Therefore, when we make a copy of an object, we have to choose what type of copy we need to make. A call to Object.assign(A, B) copies to A all the existing properties in B, thus giving us a " shallow " copy in a simple way. To make a deeper copy we would need a more complex functionality, in which perhaps we can choose the depth of the copy to be made and if we want to copy functions. If the object is deep but has no cycles or functions, we can use

const clone = JSON.parse(JSON.stringify(obj));

But this will fail in case of encountering cycles:

const obj3 = {
  p1: 'A',
  p2: 1
}

obj3.p3= obj3;

JSON.stringify(obj3);
Scroll to Top