学习视频

https://www.bilibili.com/video/BV1nh4y1374c/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=abf5496a61f07fa19906907e78de534b

在这里插入图片描述

在编程中,处理对象复制时经常会遇到 深拷贝(Deep Copy)浅拷贝(Shallow Copy) 的概念。它们的核心区别在于 引用类型数据 的复制方式。以下是详细解释及代码示例:


一、关键概念对比

特性 浅拷贝(Shallow Copy) 深拷贝(Deep Copy)
复制深度 仅复制对象的第一层属性 递归复制对象所有层级属性
引用类型处理 复制引用地址(新旧对象共享引用类型属性) 创建新的引用对象(新旧对象完全独立)
内存开销 小(仅复制指针) 大(递归创建新内存)
修改影响 修改引用类型属性会联动原对象 新旧对象完全隔离
典型实现方式 Object.assign()、展开运算符 ... JSON.parse(JSON.stringify())、递归复制函数

二、JavaScript 代码示例

1. 浅拷贝示例
// 原对象
const original = {
  name: 'John',
  address: { city: 'New York' }
};

// 浅拷贝
const shallowCopy = Object.assign({}, original);
// 或使用展开运算符:const shallowCopy = { ...original };

// 修改浅拷贝后的对象
shallowCopy.address.city = 'London';

console.log(original.address.city); // 输出: 'London'(原对象被修改)
2. 深拷贝示例
// 简单深拷贝(有局限性)
const deepCopySimple = JSON.parse(JSON.stringify(original));

// 修改深拷贝后的对象
deepCopySimple.address.city = 'Paris';

console.log(original.address.city); // 输出: 'New York'(原对象未受影响)

三、深拷贝的局限性及解决方案

1. JSON 方法的缺陷
const obj = { 
  date: new Date(),          // Date 对象会被转为字符串
  func: () => console.log('test'),  // 函数会被丢弃
  symbol: Symbol('key'),     // Symbol 会被忽略
  undefined: undefined,      // undefined 属性会丢失
  infinity: Infinity,        // 会被转为 null
  regexp: /pattern/g         // 正则会被转为空对象 {}
};

const badDeepCopy = JSON.parse(JSON.stringify(obj));
console.log(badDeepCopy); 
// 输出: { date: "2023-03-15T12:00:00.000Z", regexp: {} }
2. 可靠深拷贝实现
function deepClone(obj, hash = new WeakMap()) {
  // 处理循环引用
  if (hash.has(obj)) return hash.get(obj);

  // 处理特殊对象类型
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  if (typeof obj !== 'object' || obj === null) return obj;

  // 创建新对象/数组
  const clone = Array.isArray(obj) ? [] : {};
  hash.set(obj, clone);

  // 递归复制属性
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], hash);
    }
  }

  // 处理 Symbol 键
  const symbols = Object.getOwnPropertySymbols(obj);
  for (const sym of symbols) {
    clone[sym] = deepClone(obj[sym], hash);
  }

  return clone;
}

// 使用示例
const complexObj = { a: 1, b: { c: 2 }, d: [3, { e: 4 }] };
const goodDeepCopy = deepClone(complexObj);

四、不同语言的拷贝特性

语言 默认赋值行为 浅拷贝方式 深拷贝方式
JavaScript 浅拷贝 Object.assign(), [...arr] JSON方法、递归函数、lodash.cloneDeep
Python 浅拷贝 copy.copy() copy.deepcopy()
Java 引用传递 clone()(需实现接口) 序列化/反序列化
C++ 按值复制 默认赋值 需手动实现拷贝构造函数

五、使用场景建议

1. 使用浅拷贝的场景
  • 对象结构简单,无嵌套引用类型
  • 需要快速复制且内存敏感
  • 明确需要共享部分数据(如缓存共享配置)
2. 使用深拷贝的场景
  • 状态管理(如 Redux 中的不可变数据)
  • 需要完全隔离的配置副本
  • 复杂数据结构的备份/恢复

六、性能优化技巧

  1. 按需深拷贝:只拷贝需要修改的部分属性
  2. Immutable.js:使用不可变数据结构库优化
  3. 结构化克隆:利用浏览器原生能力(兼容性要求)
    // 浏览器API(需兼容性检查)
    const cloned = structuredClone(original);
    

通过理解深浅拷贝的机制,可以避免因引用共享导致的隐蔽 Bug,同时根据场景合理选择拷贝策略以平衡性能与安全性。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐