深拷贝问题

1. JSON.parse(JSON.stringify()) 方法实现深拷贝

优点:

  • 简单快捷

缺点:

  • 无法处理对象之间的深层次引用
let a = {};
let b = { a };
a.b = b;

let copyObj = JSON.parse(JSON.stringify(a));
console.log(copyObj);  // TypeError
  • 如果对象含有Map/Set/RegExp/Date等内置类型,会出现丢失数据的问题
let a = {};
let b = new Set();
b.add(123);
a.s = b;

let copyObj = JSON.parse(JSON.stringify(a));
console.log(a);  // { s:Set {123} }
console.log(copyObj);  // { s: {} } set 丢失。
  • 如果数据过大,在解析为对象形式时,内存消耗大。
let jsonObj = JSON.parse(JSON.stringify(obj));

2. ES5简单实现

此方法仍不能解决对象深层次引用和内置类型数据丢失的问题。

function deepClone(origin, target) {
  var tar = target || {};

  for (var k in origin) {
    if (origin.hasOwnProperty(k)) {
      if (typeof origin[k] === 'object' && origin[k] !== null) {
        tar[k] = Object.prototype.toString(origin[k]) === '[object Array]' ? [] : {};
        deepClone(origin[k], tar[k]);
      } else {
        tar[k] = origin[k];
      }
    }
  }

  return tar;
}

3. ES6 实现

通过借助ES6weakMap来解决重复对象之间引用的问题。

function deepClone(origin, hashMap = new WeakMap()) {
  // 如果是值类型直接返回。
  if (origin == undefined || typeof origin !== 'object') {
    return origin;
  }

  // 用于解决内置类型丢失问题
  if (origin instanceof Date) {
    return new Date(origin);
  }

  if (origin instanceof RegExp) {
    return new RegExp(origin);
  }

  if (origin instanceof Set) {
    return new Set(origin);
  }

  if (origin instanceof Map) {
    return new Map(origin);
  }

  const hashkey = hashMap.get(origin);

  if (hashkey) {
    return hashkey;
  }

  const target = new origin.constructor();
  // 相当于 Array.isarray(origin)?[]:{}; / tar[k] = Object.prototype.toString(origin[k]) === '[object Array]' ? [] : {};

  hashMap.set(origin, target);

  // 针对 symbol类型
  const symKeys = Object.getOwnPropertySymbols(origin);
  if (symKeys.length > 0) {
    symKeys.forEach(s => {
      if (typeof origin[s] === 'object' && origin[s] !== null) {
        target[s] = deepClone(origin[s]);
      } else {
        target[s] = origin[s];
      }
    })
  }

  for (let k in origin) {
    if (origin.hasOwnProperty(k)) {
      target[k] = deepClone(origin[k], hashMap);
    }
  }

  return target;
}
有问题欢迎指出,一起探讨学习!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值