Shallow copy and deep copy in js

In the process of front-end development, we often encounter the problems of shallow copy and deep copy,
The following is a brief description of the concept, difference and implementation method of shallow copy and deep copy.

concept

Shallow copy:

Shallow copy means that a new object accurately copies the attribute value of the original object. If it is a basic data type, it is the value of the basic data type. If it is a reference data type, it is the memory address. If the reference memory address of one object changes, the other object will also change.

Deep copy:

Compared with shallow copy, if the attribute value is a reference type, it creates a new reference type and copies the corresponding value to it. Therefore, the object obtains a new reference type instead of an original reference type. Deep copy can be implemented with two functions of JSON for some objects. However, because the object format of JSON is more strict than that of js, the conversion will fail if a function or Symbol type value appears in the attribute value.

difference

When the object type is copied, the shallow copy only copies the first layer attributes of the object, and the deep copy can recursively copy the attributes of the object.

Implementation method

Implementation method of shallow copy:

1,Object.assign()

Object.assign() is the copy method of the object in ES6. The first parameter accepted is the target object, and the other parameters are the source object. Usage: object Assign (target, source_1, ···), which can realize shallow copy and deep copy of one-dimensional object.

This method should pay attention to:

  • If the target object and the source object have properties with the same name, or multiple source objects have properties with the same name, the subsequent properties will overwrite the previous properties.
  • If the function has only one parameter, when the parameter is an object, the object is returned directly; When the parameter is not an object, it will be converted to an object and then returned.
  • Because null and undefined cannot be converted into objects, the first parameter cannot be null or undefined, and an error will be reported.
let target = {a: 1};
let object2 = {b: 2};
let object3 = {c: 3};
Object.assign(target,object2,object3);  
console.log(target);  // {a: 1, b: 2, c: 3}

2. Extension operator

Using the extension operator, you can copy attributes when constructing literal objects. Syntax: let cloneObj = {... obj}.

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

3. Array method to realize shallow copy of array

(1)Array.prototype.slice

slice() method is a method of JavaScript array. This method can return the selected element from the existing array: Usage: array Slice (start, end), which does not change the original array.
This method has two parameters, both of which are optional. If both parameters are not written, a shallow copy of an array can be realized.

let arr = [1,2,3,4];
console.log(arr.slice()); // [1,2,3,4]
console.log(arr.slice() === arr); //false

(2)Array.prototype.concat

The concat() method is used to combine two or more arrays. This method does not change the existing array, but returns a new array. This method has two parameters, both of which are optional. If both parameters are not written, a shallow copy of an array can be realized.

let arr = [1,2,3,4];
console.log(arr.concat()); // [1,2,3,4]
console.log(arr.concat() === arr); //false

Implementation method of deep copy:

1,JSON.stringify()

JSON.parse(JSON.stringify(obj)) is one of the commonly used deep copy methods. Its principle is to use JSON Stringify serializes js objects (JSON strings), and then uses JSON Parse to deserialize (restore) js objects.
This method can simply and rudely implement deep copy, but there are still problems. If there are functions, undefined and symbol in the copied object, when JSON is used After stringify () is processed, it will disappear.

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

2. Function library lodash cloneDeep method

The library also provides cloneDeep is used for Deep Copy

var _ = require('lodash');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);// false

3. Handwritten implementation of deep copy function

// Implementation of deep copy
function deepCopy(target, map = new WeakMap()) {
  let result = null
  if(Array.isArray(target)){
    result = []
  }else{
    result = {}
  }
  //Handling circular dependencies
  if(map.get(target)){
    return map.get(target)
  }else{
    map.set(target.result)
  }

  for (let i in target) {
    if (target.hasOwnProperty(i)) {
      if(typeof target[i] === 'object'){
        result[i] = deepClone(target[i], map)
      }else{
        result[i] = target[i]
      }
    }
  }
  return result
}

Keywords: Javascript Front-end

Added by bing_crosby on Thu, 10 Feb 2022 13:34:32 +0200