# 深度克隆

对象的浅克隆,使用Object.assign或扩展符(...)就可以实现。

什么是浅克隆?

基础类型数据(boolStringNumberundefinednull)都可以克隆,而引用类型的数据(ArrayObjectFunction等)只是引用过来而已

来段代码了解一下:

const date = new Date();
const arr = [];
const o = {};
const obj = {
  date,
  arr,
  o
};
var newObj = {};
Object.assign(newObj, obj);
//或者换成扩展符,效果是一样的
//var newObj = {...obj};

//我们给arr添加一条数据:
arr.push(123);
o['a'] = 'abc';
date.setDate(13);

console.log(newObj.arr);//会看到它的arr属性的值也变化了

深度克隆的需求还是很常见的。因为函数重新赋值后,与它本身就没有关系了,所以我们只需要考虑typeofobject的情况。一般是对象、数组、DateSet

下面是个简单的实现:

function isSet(obj) {
  return Object.prototype.toString.call(obj) === '[object Set]';
}

function clone(obj) {
  if (!obj || typeof obj !== 'object') {
    return obj;
  }
  if (isSet(obj)) {
    var newSet = new Set();
    for (var prop of obj) {
      newSet.add(clone(prop));
    }
    return newSet;
  } else if (obj instanceof Array) {
    if (!Array.isArray(obj)) {
      obj = Array.from(obj);
    }
    return obj.map((item) => {
      return clone(item);
    });
  } else if(obj instanceof Date){
    return new Date(obj);
  } else {
    var newObj = {};
    for (var key in obj) {
      newObj[key] = clone(obj[key]);
    }
    return newObj;
  }
}

测试一下:

const date = new Date();
const arr = [];
const o = {};
const set = new Set([1, 2]);
const fn = ()=>{console.log('------------before------')};
const obj = {
  date,
  arr,
  o,
  set,
  fn
};
const newObj = clone(obj, true);
arr.push(1);
o['a'] = 'abc';
date.setDate(13);
set.add(3);
obj.fn = ()=>{console.log('------------after------')};
console.log(newObj);
newObj.fn();