【前端面试题】深拷贝的终极实现_前端深拷贝

普通版

function deepClone(origin, target) {
  // 判断target是否传入,如果未传入则创建一个{}
  let tar = target || {}; 
  // 遍历origin对象
  for (var key in origin) {
    // 判断是否origin的自有属性
    if (origin.hasOwnProperty(key)) {  
      // 如果值是对象并且不为null,递归调用
      if (typeof origin[key] === 'object' && origin[key] !== null) {  
        // 根据值是否为数组创建初始化对象或数组
        tar[key] = Array.isArray(origin[key]) ? [] : {};
        // 递归调用 
        deepClone(origin[key], tar[key]);
      } else {  
        // 如果是简单类型,直接复制值
        tar[key] = origin[key];
      }
    }
  }
  // 返回最终拷贝完的值
  return tar;
}

复制代码

这个深拷贝方法通过判断属性的值类型,实现了对 对象数组 以及 DateRegExp 等引用类型对象的递归拷贝,同时也考虑了拷贝基本类型值的情况,能够满足大多数场景的要求。

最终版

为什么还有最终版?

上面的案例,可以应对一般场景。

但是对于有两个对象相互拷贝的场景,会导致循环的无限递归,造成死循环!

Uncaught RangeError: Maximum call stack size exceeded

场景:

如何解决无限递归的问题?

首先我们要了解 WeakMap: WeakMap 的键名所引用的对象都是弱引用,不会被垃圾回收机制考虑,所以当对象只被WeakMap引用时,其所占用的内存会被垃圾回收。

而通过 WeakMap 记录已经拷贝过的对象,能防止循环引用导致的无限递归。

代码

实现简述:利用 WeakMap() 在属性遍历完绑定,并在每次循环时获取当前键名,如果存在则返回数据,不存在则拷贝。

function deepClone(origin, hashMap = new WeakMap()) {
    // 判断是否是对象
    if (origin == undefined || typeof origin !== 'object') return origin;
    // 判断是否是Date/RegExp类型
    if (origin instanceof Date) return new Date(origin);
    if (origin instanceof RegExp) return new RegExp(origin);

    // 判断是否已经克隆过此对象, 如果是直接返回
    const hashKey = hashMap.get(origin);
    if (hashKey) return hashKey;

    // *利用原型构造器获取新的对象 如: [], {}
    const target = new origin.constructor();
    // 将对象存入map
    hashMap.set(origin, target);
    // 循环遍历当前层数据
    for (let k in origin) {
        // 判断当前属性是否为引用类型
        if (origin.hasOwnProperty(k)) {
            target[k] = deepClone(origin[k], hashMap);
        }
    }
    return target;
}
复制代码

我们再来看一下使用最新版后的两个对象互相拷贝:

可以看到,通过使用 WeakMap 记录已经拷贝的对象,有效防止循环引用导致的栈溢出错误,是功能最完备的深拷贝实现。

总结

深拷贝可以完全拷贝一个对象,生成两个独立的且相互不影响的对象。

明白各种深拷贝实现的思路和性能差异,可以在不同场景选用最优的方案。

大厂面试题分享 面试题库

前后端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库  web前端面试题库 VS java后端面试题库大全

文末

篇幅有限没有列举更多的前端面试题,小编把整理的前端大厂面试题PDF分享出来,一共有269页

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值