浅拷贝

深拷贝浅拷贝 - 图1

方法一:Object.assign()

  1. Object.assign(target, ...sources)
  • 不能拷贝继承属性
  • 不能拷贝不可枚举属性
  • 能拷贝Symbol 类型的属性

方法二:扩展运算符

  1. let cloneObj = { ...obj };

缺陷和 Object.assign() 一样

方法三:concat 拷贝数组

  1. let arr = [1, 2, 3];
  2. let newArr = arr.concat();
  3. newArr[1] = 100;
  4. console.log(arr); // [ 1, 2, 3 ]
  5. console.log(newArr); // [ 1, 100, 3 ]

方法四:slice 拷贝数组

  1. let arr = [1, 2, {val: 4}];
  2. let newArr = arr.slice();
  3. newArr[2].val = 1000;
  4. console.log(arr);

手动实现一个浅拷贝

  1. const shallowClone = (target) => {
  2. if (typeof target === 'object' && target !== null) {
  3. const newTarget = Array.isArray(target) ? [] : {};
  4. for (let pro in target) {
  5. if (target.hasOwnProperty(pro)) {
  6. newTarget[pro] = target[pro];
  7. }
  8. }
  9. return newTarget;
  10. }
  11. return target;
  12. }

深拷贝

深拷贝浅拷贝 - 图2

方法一:JSON.stringify

  1. let obj1 = { a:1, b:[1,2,3] }
  2. let str = JSON.stringify(obj1);
  3. let obj2 = JSON.parse(str);
  4. console.log(obj2);
  • 拷贝的对象如果有函数、undefined、symbol ,会被清除,键值对消失
  • 拷贝的 Date 引用类型,会变成字符串
  • 拷贝的 RegExp 引用类型,会变成空对象
  • 拷贝的对象含有 NaN、Infinity、-Infinity 会变成null
  • 不能拷贝不可枚举属性
  • 不能拷贝对象的原型链
  • 不能拷贝对象的循环引用

手动实现一个深拷贝

  1. const isComplexDataType = obj => (
  2. typeof obj === 'object'
  3. ) && (obj !== null)
  4. const deepClone = function (obj, hash = new WeakMap()) {
  5. // 日期对象直接返回一个新的日期对象
  6. if (obj.constructor === Date) {
  7. return new Date(obj);
  8. }
  9. // 正则对象直接返回一个新的正则对象
  10. if (obj.constructor === RegExp) {
  11. return new RegExp(obj);
  12. }
  13. // 如果循环引用了就用 weakMap 来解决
  14. if (hash.has(obj)) {
  15. return hash.get(obj);
  16. }
  17. // 利用Object 的 getOwnPropertyDescriptors 方法可以获得对象的所有属性,以及对应的特性,
  18. // 结合 Object 的 create 方法创建一个新对象,并继承传入原对象的原型链;
  19. let allDesc = Object.getOwnPropertyDescriptors(obj)
  20. let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)
  21. hash.set(obj, cloneObj)
  22. for (let key of Reflect.ownKeys(obj)) {
  23. // 针对能够遍历对象的不可枚举属性以及 Symbol 类型,我们可以使用 Reflect.ownKeys 方法;
  24. cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function')
  25. ? deepClone(obj[key], hash)
  26. : obj[key];
  27. }
  28. return cloneObj
  29. }