JavaScript - 深拷贝

301 阅读1分钟

1、Es5的实现方式

var obj = {
  name: "张三",
  age: 34,
  info: {
    hobby: ["足球", "篮球","乒乓球"]
  }
}

function deepClone( resource ){
    let target;
    let type = Object.prototype.toString.call(resource).slice(8,-1);
    if( typeof resource == "object" ){
        target =  type === "Array" ? [] : {};
        for( let key in resource ){
            if( resource.hasOwnProperty( key)){
                if( typeof resource[key] =="object"){
                    target[key] = deepClone( resource[key] )
                }else{
                    target[key] = resource[key];
                }
            }
        }
    }else{
        target = resource;
    }
    return target;
}

var newObj = deepClone(obj)
newObj.info.hobby[0] = "台球";
console.log(obj,newObj)

2、Es6的实现方式

// map和wekMap的区别:
// 1、map的键可以是任意值,wekMap的键必须是对象
// 2、weakMap的键是弱引用,删除key之后,所有的引用都会被垃圾回收


// hashMap:避免对象相互引用,出现死递归
function deepClone(origin, hashMap = new WeakMap()) {

  if ((origin == undefined) || (typeof origin !== "object")) {
    return origin
  };

  // 判断当前对象是否拷贝过( 避免对象的相互引用引起的死循环 ) 
  const hashKey = hashMap.get(origin);
  if (hashKey) return hashKey;

  // 利用constructor属性,创建出新的对象或数组
  const target = new origin.constructor();
  hashMap.set(origin, target);
  for (let k in origin) {
    if (origin.hasOwnProperty(k)) {
      target[k] = deepClone(origin[k], hashMap);
    }
  }
  return target;
}

var obj1 = {};
var obj2 = {};
obj2.obj1 = obj1;
obj1.obj2 = obj2;

//1、不使用hashMap会出现死递归
//2、使用hashMap内部循环只会触发两次
deepClone(obj2)