So before we look at deep copy, what is deep copy?

In JS, data types are divided into basic data types and reference data types. For basic data types, its value is stored directly in stack memory, while for reference types, it only stores a reference in stack memory, while the real data is stored in heap memory

When we manipulate data, two things happen

Basic data types

var a = 3;
var b = a;
b = 5;
console.log(a); / / 3
console.log(b); / / 5
Copy the code

What you can see is that for primitive types, we assign the value of a primitive type to variable A, and then we assign the value of A to variable B; And then we modify b; You can see that b is modified, but the value of A is not. Both variables use independent data

2. Reference data types

var obj1 = {
    a:  1.b:  2.c:  3
}
var obj2 = obj1;
obj2.a = 5;
console.log(obj1.a);  / / 5
console.log(obj2.a);  / / 5
Copy the code

What you can see is that both objects have been modified. The object is the value of the reference type. For the reference type, when we assign obj1 to obj2, we’re just assigning obj1’s stack reference to obj2, and both objects are pointing to the same data in the heap. So when we modify any value, we are modifying the data in the heap, not the reference, so as long as we modify, the value of the referenced object is automatically changed

In fact, the above example is a simple shallow copy,

Article topic, deep copy!

Shallow copy

For shallow copies, only the reference to the object is copied, but the value of the object is not deeply copied. Multiple objects point to the same object in heap memory, and any modification causes all objects to change their value because they share a single data

Deep copy

In a real project, we definitely can’t have every object value pointing to the same heap memory, which is not easy for us to do operations, so naturally born deep copy deep copy function on the reference type! For example, Object and Array deep copy does not copy the references of the reference type, but copies all the values of the reference type to form a new reference type. In this way, the problem of reference confusion does not occur, so that we can use the same data for many times without worrying about data conflicts

Third, the implementation of deep copy

1. Take a look at the beggar’s deep copy first! JSON. Stringify (), and JSON. The parse ()

 var obj1 = {
    a: 1.b: 2.c: 3
}
var objString = JSON.stringify(obj1);
var obj2 = JSON.parse(objString);
obj2.a = 5;
console.log(obj1.a);  / / 1
console.log(obj2.a); / / 5
Copy the code

You can see that there is no reference problem, and changing obj2’s data does not affect obj1 at all. But why is it beggar’s version? That’s because with json.stringify () and json.parse () it can’t copy undefined, function, RegExp, etc

Object. Assign (target, source)

  var obj1 = {
    a: 1.b: 2.c: 3
}
var obj2 = Object.assign({}, obj1);
obj2.b = 5;
console.log(obj1.b); / / 2
console.log(obj2.b); / / 5
Copy the code

The second approach doesn’t seem to have any problems either, but this is one layer of objects, if there are multiple layers of nesting

  var obj1 = {
    a: 1.b: 2.c: ['a'.'b'.'c']}var obj2 = Object.assign({}, obj1);
obj2.c[1] = 5;
console.log(obj1.c); // ["a", 5, "c"]
console.log(obj2.c); // ["a", 5, "c"]
Copy the code

3. The third way is recursive copy

  // Define a deep-copy function that takes the target argument
function deepClone(target) {
    // Define a variable
    let result;
    // If it is an object that needs a deep copy
    if (typeof target === 'object') {
    // If it is an array
        if (Array.isArray(target)) {
            result = []; // Assign result to an array and iterate
            for (let i in target) {
                // Recursively clone each item in the array
                result.push(deepClone(target[i]))
            }
         // Determine if the current value is null; Directly assign to null
        } else if(target===null) {
            result = null;
         // If the current value is a RegExp object, assign it directly
        } else if(target.constructor===RegExp){
            result = target;
        }else {
         // If the object is a normal object, the direct for in loop assigns all the values of the object recursively
            result = {};
            for (let i intarget) { result[i] = deepClone(target[i]); }}// If it is not an object, it is a primitive data type
    } else {
        result = target;
    }
     // Return the final result
    return result;
}
Copy the code
See the effect
       let obj1 = {
        name: {
            c: /a/,
            d: undefined.b: null
        },
        ext: function () {
            console.log(this.a)
        },
        lab: [{a: 'c'.b: /b/,
                c: undefined
            },
            'a'.3]}let obj2 = deepClone(obj1);
        console.log(obj2);
Copy the code

You can see that the final copy result is null, undefinde, function, RegExp and other special values are also copied successfully, and there is no problem in modifying the values inside. There are still many problems unsolved

The artifacts are at the back

4. Parse the data into strings using JSON methods, and then convert it into JSON object data

       let obj1 = {
        name: {
            c: /a/,
            d: undefined.b: null
        },
        ext: function () {
            console.log(this.a)
        },
        lab: [{a: 'c'.b: /b/,
                c: undefined
            },
            'a'.3]}let obj2 = JSON.parse(JSON.stringify(obj1));
        console.log(obj2);
Copy the code

As you can see, the method can not be copied, some difficult to parse also can not be resolved, so, this is convenient and quick, need to note that I usually use this method to copy, always step on the pit