浅拷贝

创建一个新对象,这个对象有这原始对象属性值的一份精确拷贝。如果属性是基本数据类型,拷贝的就是基本类型的值,如果是引用类型,拷贝的就是内存地址。所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

  1. // 浅克隆的方法如下
  2. Object.assign(target,...source)
  3. let target = {};
  4. let source = {a:{b:2}}
  5. Object.assign(target,source);
  6. target.a === source.a //true

深拷贝

将一个对象从内存中完成的拷贝一份出来,从堆内存中开辟一个新的区域存放新的对象,且修改新对象不会影响原对象。

  1. const isComplexDataType = obj => typeof obj === "object";
  2. const deepClone = function(obj, hash = new WeakMap()) {
  3. if (hash.has(obj)) return hash.get(obj);
  4. let type = [Date, RegExp, Set, Map, WeakMap, WeakSet];
  5. if (type.includes(obj.constructor)) return new obj.constructor(obj);
  6. // 如果成环了,参数obj = obj.loop = 最初obj会在WeakMap中找到第一次放入的obj提前返回,第一次放入WeakMap的cloneObj
  7. // 遍历传入参数所有键的特性
  8. let allDesc = Object.getOwnPropertyDescriptors(obj);
  9. // 继承原型
  10. let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);
  11. hash.set(obj, cloneObj);
  12. for (let key of Reflect.ownKeys(obj)) {
  13. // Reflect.ownKeys(obj)可以拷贝不可枚举属性和符号类型
  14. // 如果值是引用类型(非函数)则递归调用deepClone
  15. cloneObj[key] =
  16. isComplexDataType(obj[key]) && typeof obj[key] !== "function"
  17. ? deepClone(obj[key], hash)
  18. : obj[key];
  19. }
  20. return cloneObj;
  21. };