directory

  1. Deep copy – cyclic reference treatment weakMap writing method I
  2. Deep copy – cyclic reference treatment weakMap writing method ii
  3. Recursion – there are problems with circular references
  4. Recursion – Solves circular references

I. Deep copy-cyclic reference treatment weakMap writing method 1


function deepCopy(obj) {
  // Hash table to record the reference relation of all objects
  let map = new WeakMap(a);function dp(obj) {
    let result = null;
    let keys = Object.keys(obj);
    let key = null,
      temp = null,
      existobj = null;

    existobj = map.get(obj);
    // If the object is already logged, return it
    if (existobj) {
      return existobj;
    }

    result = {}
    map.set(obj, result);

    for (let i = 0, len = keys.length; i < len; i++) {
      key = keys[i];
      temp = obj[key];
      if (temp && typeof temp === 'object') {
        result[key] = dp(temp);
      } else{ result[key] = temp; }}return result;
  }
  return dp(obj);
}




const obj1 = {
  x: 1
}
// obj1.z = obj1;

const obj2 = {
  x: 2
}

obj1.next = obj2;
obj2.next = obj1;


const obj3 = deepCopy(obj1);

console.log(obj3)

Copy the code

Deep copy-cyclic reference weakMap writing method ii

// Use the Map function
function deepCopy(obj,map = new Map(a)){
    if (typeofobj ! ='object') return 
    var newObj = Array.isArray(obj)? [] : {}if(map.get(obj)){ 
      return map.get(obj); 
    } 
    map.set(obj,newObj);
    for(var key in obj){
        if (obj.hasOwnProperty(key)) {
            if (typeof obj[key] == 'object') {
                newObj[key] = deepCopy(obj[key],map);
            } else{ newObj[key] = obj[key]; }}}return newObj;
}
const obj1 = {
        x:1.y:2.d: {a:3.b:4
         }
    }
  obj1.z = obj1;
  const obj2 = deepCopy(obj1);
  console.log(obj2)
            
/ / output node {x: 1, y: 2 d: 4} {3, a: b:, z: [Circular]}
// Console output {x: 1, y: 2, d: {... }, z: {... }}

Copy the code

Triple recursion – there are problems with circular references

The following methods cannot be handled correctly if there is a circular reference in the object

function deepCopy(obj) {
  // Create a new object
  let result = {}
  let keys = Object.keys(obj),
    key = null,
    temp = null;

  for (let i = 0; i < keys.length; i++) {
    key = keys[i];  
    temp = obj[key];
    // If the value of the field is also an object, the operation is recursive
    if (temp && typeof temp === 'object') {
      result[key] = deepCopy(temp);
    } else {
    // Otherwise assign directly to the new objectresult[key] = temp; }}return result;
}

const obj1 = {
  x: {
    m: 1
  },
  y: undefined.z: function add(z1, z2) {
    return z1 + z2
  },
  a: Symbol("foo")};const obj2 = deepCopy1(obj1);
obj2.x.m = 2;

console.log(obj1); //{x: {m: 1}, y: undefined, z: ƒ, a: Symbol(foo)}
console.log(obj2); //{x: {m: 2}, y: undefined, z: ƒ, a: Symbol(foo)}
Copy the code

Quad recursion – Solves circular references

1) Parent reference

A parent reference is a reference to a property of an object, which is the object itself. If we were to make a deep copy, it would be in the child element -> parent object -> child element… This loop continues, causing stack overflow. Take this example:

 const obj1 = {
  x: 1.y: 2
};
obj1.z = obj1;

constobj2 = deepCopy1(obj1); \ \ stack overflowCopy the code

The deepCopy function can be modified by simply checking whether an object’s fields reference the object or any parent of the object:


function deepCopy2(obj, parent=null) {
  // Create a new object
  let result = {};
  let keys = Object.keys(obj),
     key = null,
     temp = null,
     _parent = parent;
  // If the field has a parent, you need to trace the parent of the field
  while(_parent) {
    // If the field references its parent, it is a circular reference
    if(_parent.originParent === obj) {
      // A circular reference returns a new object of the same class
      return _parent.currentParent;
    }
    _parent = _parent.parent
  }
  for(let i=0,len=keys.length; i<len; i++) { key = keys[i] temp = obj[key]// If the value of the field is also a new object
    if(temp && typeof temp === 'object') {
      result[key] = deepCopy2(temp, {
        // Perform deep copy recursively, passing the peer object to be copied and the new object to parent, facilitating the traceability of circular references
        originParent: obj,
        currentParent: result,
        parent: parent
      });
    } else{ result[key] = temp; }}return result;
}

const obj1 = {
  x:1
}
obj1.z = obj1;

const obj2 = deepCopy2(obj1);

Copy the code

2) Peer references

Test cases to be supplemented:



Copy the code

Solution: A parent reference is A reference, and A non-parent reference is A reference, so just record all objects in object A and match them to the newly created object.

reference

  • Deep copy
  • Deep copy – by me

conclusion