javascript's research on deep copy objects

For deep copy, the concept of shallow copy is not much said, the concept can be Baidu yo! Here are some research on deep copy objects!

Only deep copy of value type data

For data objects with only values, the following line is enough!

JSON.parse(JSON.stringify(obj))

A simple, unstructured, deep copy

function clone(source) {
    var target = {};
    for(var i in source) {
        if (source.hasOwnProperty(i)) {
            if (typeof source[i] === 'object') {
                target[i] = clone(source[i]); // Pay attention here.
            } else {
                target[i] = source[i];
            }
        }
    }

    return target;
}

Problems:

  • No inspection of parameters
  • The logic of judging whether the object is not rigorous enough
  • Array compatibility is not considered

Advanced deep copy

function isObj(obj)
{
    return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}

function deepCopy(obj)
{
    let tempObj = Array.isArray(obj) ? [] :{};
    for(let key in obj)
    {
        tempObj[key] = isObj(obj[key]) ? deepCopy(obj[key]) : obj[key];
    }
    return tempObj;
}

Problems:

  • There is a problem with the copy ring, that is, the copy of the circular reference to the object

Deep copy for ring

You can use a WeakMap structure to store the copied object. When copying, you first query the WeakMap to see if the object has been copied. If it has been copied, take out the object and return it. Modify the deepCopy function as follows:

function isObj(obj)
{
    return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}
function deepCopy(obj, hash = new WeakMap()) {    
    if(hash.has(obj)) return hash.get(obj)    
    let cloneObj = Array.isArray(obj) ? [] : {}
    hash.set(obj, cloneObj)    
    for (let key in obj) {
        cloneObj[key] = isObj(obj[key]) ? deepCopy(obj[key], hash) : obj[key];
    }   
    return cloneObj
}

Problems:

  • No consideration is given to the copy of new Date(), regular, function type objects

Combining ring, for deep copy of date,reg, arrow function type


const obj = {    arr: [111, 222],    obj: {key: 'object'},    a: () => {console.log('function')},    date: new Date(),    reg: /regular/ig}

function isObj(obj)
{
    return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}
function deepCopy(obj, hash = new WeakMap()) {  
      let cloneObj;   
      let Constructor = obj.constructor; 
      switch(Constructor){       
        case RegExp:
            cloneObj = new Constructor(obj)         
            break;
        case Date:
            cloneObj = new Constructor(obj.getTime())           
            break;
        case Function:
            cloneObj = eval(obj.toString());
            break;
        default:           
         if(hash.has(obj)) return hash.get(obj)
            cloneObj = new Constructor()
            hash.set(obj, cloneObj)
      }   

      for (let key in obj) {
            cloneObj[key] = isObj(obj[key]) ? deepCopy(obj[key], hash) : obj[key];
      }    
      return cloneObj;
}

const cloneObj = deepCopy(obj);
console.log(cloneObj);

For more legacy problems, copy functions. If function is not an arrow function, how to solve it? Also, do you want to copy the properties on the prototype chain? How to copy non enumeration properties? How to copy Error objects and so on?

Keywords: Javascript JSON

Added by insight on Mon, 02 Dec 2019 11:57:50 +0200