# Deep and shallow copies

How to distinguish between deep copy and shallow copy? To put it simply, assume that B copies A. when modifying a, see whether B will change. If B also changes, it means that this is a shallow copy. If B does not change, it is a deep copy.

If it is a basic data type, the name and value will be stored in the stack memory

```var a = 1;
b = a; // Stack memory will open up a new memory space. At this time, b and a are independent of each other
b = 2;
console.log(a); // 1
a = 3
console.log(b); // 2
```

Of course, this is not a deep copy, because the deep copy itself is only for more complex object type data.

```var a = [1]
var b = a // Shallow copy
var c = [...a] // Deep copy
a.push(2)
console.log(b); // [1,2]
console.log(c); // [1]
b.push(3)
console.log(a) // [1,2,3]
```

2 if it is a reference data type, the name is stored in the stack memory and the value is stored in the heap memory, but the stack memory will provide a reference address to point to the value in the heap memory:

Shallow copy: when b=a is copied, the reference address of a is copied instead of the value in the heap:

When we modify the array when a[0]=1, because a and b point to the same address, naturally b is also affected:

In order to realize deep copy, a new memory should be opened in the heap memory to store values for b, just like the basic type:

Why [] = = [] is false: each time [] is used, a new array object is created. When arrays are compared, their references are actually compared. [] = = [] Although both sides are [], both sides are not equal in terms of reference.

Method for realizing shallow copy

(1) for ··· in only circulates the first layer

```function simpleCopy(obj1) {
var obj2 = {}
for (let i in obj1) {
obj2[i] = obj1[i];
}
return obj2;
}
var obj1 = {
a: 1,
c: {
d: 3
}
}
var obj2 = simpleCopy(obj1);
obj2.a = 11;
obj2.c.d = 33;
console.log(obj1.a); // 1
console.log(obj2.a); // 11
console.log(obj1.c.d); // 33
console.log(obj2.c.d); // 33
```

(2) Object.assign method

```var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a) // 3
```

(3) Direct use = assignment

```var a = [0,2,3];
var b = a;
a[0] = 1;
console.log(a) // [1,2,3]
console.log(b) // [1,2,3]
```

Method for realizing deep copy

(1) Use recursion to copy all hierarchical attributes

```function deepClone(obj) {
let objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
//Judge whether the ojb child element is an object. If so, copy recursively
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = deepClone(obj[key]);
} else {
//If not, simply copy
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a = [1, 2, 3, 4],
b = deepClone(a);
a[0] = 2;
console.log(a); // [ 2, 2, 3, 4 ]
console.log(b);  // [ 1, 2, 3, 4 ]
```

(2) Realize deep copy through JSON object

```function deepClone2(obj) {
var _obj = JSON.stringify(obj) // The JSON.stringify() method is used to convert JavaScript values to JSON strings.
var objClone = JSON.parse(_obj) // Use the JSON.parse() method to convert the data into JavaScript objects
return objClone;
}
var o1 = {
a: 1,
b: {
c: 2
},
f: function () {
console.log(1)
}
}
var o2 = deepClone2(o1)
o1.a = 11
o1.b.c = 22
console.log(o1); // { a: 11, b: { c: 22 }, f: [Function: f] }
console.log(o2); // { a: 1, b: { c: 2 } }
```

Disadvantages: unable to implement the deep copy of the method in the object, and it will be displayed as undefined

(3) Implementation of deep copy with lodash function library

```let b = _.cloneDeep(a)
```

(4)Object.assign
If the value of the object is a basic type, you can also use Object.assign to implement deep copy, but assign it to an empty object:

```var obj = {
a: 1,
}
var obj1 = Object.assign({}, obj); // obj is assigned to an empty {}
obj.a = 2;
console.log(obj1.a) // 1
```

(5) Deep copy of array with slice

Note: when the values in the array are basic data types, such as String, Number and Boolean, they belong to deep copy
When the value in the Array is a reference data type, such as Object and Array, it belongs to shallow copy

```var arr1 = [1, 2, 3];
var arr2 = arr1.slice(0);
arr2[1] = 0;
console.log(arr1); // [1,2,3]
console.log(arr2); // [1,0,3]
```

(6) Deep copy of array with concat

```// When the values in the array are basic data types, such as String, Number and Boolean, they belong to deep copy (the same as slice)
var arr1 = [1, 2, 3];
var arr2 = arr1.concat();
arr2[1] = 0;
console.log(arr1); // [1,2,3]
console.log(arr2); // [1,0,3]
// When the value in the Array is a reference data type, such as Object and Array, it belongs to shallow copy
var arr1 = [{ a: 1 }];
var arr2 = arr1.concat();
arr2[0].a = 2
console.log(arr1[0].a); // 2
console.log(arr2[0].a); // 2
```

(7) Deep copy using extended operators
Similarly, it is similar to slice and concat:
When value is a basic data type, such as String, Number and Boolean, you can use the extension operator for deep copy;
When value is a value of reference type, such as Object and Array, only the reference address is copied, so it belongs to shallow copy.

```var o1 = {
a: 1,
b: {
c: 2
}
}
var o2 = { ...o1 }
o1.a = 11
o1.b.c = 22
console.log(o2.a); // 1
console.log(o2.b.c); // 22
```

Tags: Javascript

Posted on Mon, 06 Sep 2021 20:34:31 -0400 by rallokkcaz