js原生深拷贝

/*****************************************************************************************/
原生js实现深拷贝 

function clone(target){
    if(typeof target === 'object'){
        let obj = Array.isArray(target) ? [] : {}
        for(const key in target ){
            obj[key] = clone(target[key])
        }
        return obj;
    }else{
        return target;
    }
}

例子:

var obj1 = {
  name:'abc',
  age:10,
  children:{
    name:'abc-child',
    age:2
  },
  address:[1,2,3,4,56,323]
}

var obj2 = clone(obj1)   // 得出obj2对象

/*****************************************************************************************/

以上拷贝能解决大部分深拷贝问题,除了还有引用的对象;
例子:

obj1.obj = obj1 // 
var obj3 = clone(obj1) //----会报错

报错信息:  
Uncaught RangeError: Maximum call stack size exceeded
at new Map (<anonymous>)
at clone (<anonymous>:1:29)
at clone (<anonymous>:9:24)
at clone (<anonymous>:9:24)
at clone (<anonymous>:9:24)
at clone (<anonymous>:9:24)
at clone (<anonymous>:9:24)
at clone (<anonymous>:9:24)
at clone (<anonymous>:9:24)
at clone (<anonymous>:9:24)

原因:obj1的深拷贝引出了无限循环,因为obj1.obj引用了它本身;

解决办法:
1, obj1.obj = clone(obj1)
2,修改clone方法如下:

function clone(target,map=new Map()){
    if(typeof target === 'object'){
        let obj = Array.isArray(target) ? [] : {}
        if(map.get(target)){
            return target;
        }
        map.set(target,obj);
        for(const key in target ){
            obj[key] = clone(target[key])
        }
        return obj;
    }else{
        return target;
    }
}

/*优化版*/
function clone(target,map=new WeakMap()){
    if(typeof target === 'object'){
        let obj = Array.isArray(target) ? [] : {}
        if(map.get(target)){
            return target;
        }
        map.set(target,obj);
        for(const key in target ){
            obj[key] = clone(target[key])
        }
        return obj;
    }else{
        return target;
    }
}
obj1.obj = obj var obj3 = clone(obj1,map)

 

posted @ 2019-09-02 10:38  藝y  阅读(581)  评论(0编辑  收藏  举报