Deep copy and shallow copy

Posted May 25, 20203 min read

Deep copy and shallow copy

Foreword

JS data type

  • Basic data types:String, Boolean, Number, Undefined, Null
  • Reference data type:Object(Array, Date, RegExp, Function)

the difference

Different storage locations:basic data types, names and values (key-values) are stored in stack memory; reference data types, names are stored in stack memory, values are stored in heap memory, but stack memory will provide a referenced address to point to heap memory Value.

the reason:

  • The heap is larger than the stack, and the stack is faster than the stack;
  • The basic data type is stable, and the memory occupied is relatively small;
  • The size of the reference type data is dynamic and unlimited, so the value is stored in the heap;
  • Heap memory is out-of-order storage and can be directly obtained based on reference

Therefore, deep copy and shallow copy are only for reference data types.

definition

Shallow copy:only copy the pointer to an object, not the object itself, the old and new objects still share the same memory.

Deep copy:another identical object will be created. The new object and the original object do not share memory. Modifying the new object will not change the original object.

img

Difference:shallow copy only copies the first layer attributes of the object, deep copy can recursively copy the attributes of the object

Shallow copy implementation

  1. for · in only loops the first layer

     //Only copy the shallow copy of the first layer
     function simpleCopy(obj1) {
        var obj2 = Array.isArray(obj1)? []:{};
        for(let i in obj1) {
        obj2 [i]= obj1 [i];
       }
        return obj2;
     }
     var obj1 = {
        a:1,
        b:2,
        c:{
              d:3
           }
     }
     var obj2 = simpleCopy(obj1);
     obj2.a = 3;
     obj2.c.d = 4;
     alert(obj1.a); //1
     alert(obj2.a); //3
     alert(obj1.c.d); //4
     alert(obj2.c.d); //4
  2. Object.assign()

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

     let a = [0,1,2,3,4],
         b = a;
     console.log(a === b);
     a [0]= 1;
     console.log(a, b);

Deep copy implementation

Use recursion to copy all level attributes

function deepClone(obj) {
    let objClone = Array.isArray(obj)? []:{};
    if(obj && typeof obj === "object") {
        for(key in obj) {
            if(obj.hasOwnProperty(key)) {
                //Determine whether the ojb child element is an object, and if so, copy it 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, b);

Defect:When encountering two objects that refer to each other, there will be an endless loop. In order to avoid the endless loop caused by the mutually referenced objects, you should judge whether to refer to each other when traversing, and if so, exit the loop.

Copying through JSON objects(deep copying of methods in objects cannot be achieved, it will be displayed as undefined)

function deepClone2(obj) {
  var _obj = JSON.stringify(obj),
    objClone = JSON.parse(_obj);
  return objClone;
}

Deep copy through jQuery's extend method

var array = [1,2,3,4];
var newArray = $.extend(true, [], array); //true is a deep copy, false is a shallow copy

Deep copy of lodash function library

let result = _.cloneDeep(test)

Reflect method

//Acting
function deepClone(obj) {
    if(! isObject(obj)) {
        throw new Error('obj is not an object!')
    }

    let isArray = Array.isArray(obj)
    let cloneObj = isArray? [... obj]:{... obj}
    Reflect.ownKeys(cloneObj) .forEach(key => {
        cloneObj [key]= isObject(obj [key])? deepClone(obj [key]):obj [key]
    })

    return cloneObj
}