深拷贝和浅拷贝的区别?如何实现一个深拷贝函数?

深拷贝与浅拷贝的区别

深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是对象复制的两种核心方式,其核心区别在于是否复制嵌套对象以及内存独立性

  1. 浅拷贝
    • 仅复制对象的第一层属性,嵌套对象(如数组、子对象)仍与原对象共享内存地址。
    • 结果:修改新对象的嵌套属性时,原对象的对应属性也会被修改(新旧对象存在关联)。
    • 实现方式
  • Object.assign()(仅第一层深拷贝)
  • 扩展运算符 {...obj} 或 [...array](仅第一层深拷贝)
  • 数组的 concat()slice()(仅数组第一层)
  1. 深拷贝
    • 递归复制对象及其所有嵌套对象,新旧对象完全独立,无共享内存。
    • 结果:修改新对象(包括嵌套属性)不会影响原对象。
    • 适用场景:对象包含多层嵌套结构(如树形数据),需完全隔离修改。
关键区别总结(表格形式):
特性浅拷贝深拷贝
复制层级仅第一层属性所有层级(递归嵌套对象)
嵌套对象内存共享内存(修改相互影响)独立内存(修改完全隔离)
原对象是否受影响是(嵌套属性修改时)
适用数据类型单层对象、数组多层嵌套对象、复杂结构

深拷贝函数的实现方法

以下是常见深拷贝方案的代码实现及注意事项:

1. 递归实现(基础版)
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj; // 基本类型直接返回
  }
  let clone = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key]); // 递归复制嵌套属性
    }
  }
  return clone;
}

缺点

  • 未处理循环引用(如 obj.self = obj)导致栈溢出。
2. 解决循环引用的递归实现
function deepClone(obj, map = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (map.has(obj)) return map.get(obj); // 检测循环引用

  let clone = Array.isArray(obj) ? [] : {};
  map.set(obj, clone); // 缓存当前对象

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], map); // 递归并传递缓存
    }
  }
  return clone;
}

优化点

  • 使用 WeakMap 跟踪已拷贝对象,避免循环引用导致的死循环。
3. JSON序列化法
const deepClone = obj => JSON.parse(JSON.stringify(obj));

缺点

  • 忽略 undefinedSymbol 和函数;
  • 不支持 Date(转为字符串)、RegExp(转为空对象)、Map/Set 等特殊类型;
  • 循环引用直接报错。
    适用场景:无特殊类型且无循环引用的简单对象。
4. 第三方库实现(推荐生产环境使用)
  • Lodash

import _ from 'lodash';
const clonedObj = _.cloneDeep(originalObj); // 支持循环引用及特殊类型

jQuery

const clonedObj = $.extend(true, {}, originalObj); // 深度递归复制

优势

  • 内置处理循环引用、特殊数据类型(如 DateRegExp)。

深拷贝的注意事项

  1. 循环引用
    • 递归实现需通过缓存(如 WeakMap)避免无限递归。
  2. 特殊数据类型
    • DateRegExpMapSet 等需单独处理(如 new Date(obj.getTime()))。
  3. 性能问题
    • 递归深拷贝大对象可能消耗较多内存/时间,JSON方法在大型数据上较慢。
  4. 不可变对象
    • 如 StringNumber 等不可变类型无需深拷贝。
方法选择建议
场景推荐方法
简单对象(无嵌套、无特殊类型)JSON序列化
含循环引用或特殊类型递归+WeakMap 或 Lodash
生产环境复杂对象Lodash(_.cloneDeep)

完整深拷贝应覆盖所有边界情况,建议优先使用成熟的第三方库(如 Lodash),避免重复造轮子及潜在风险。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

破碎的天堂鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值