鸿蒙ArkTS中的深拷贝和浅拷贝
在编程中,处理对象复制时经常会遇到和的概念。它们的核心区别在于的复制方式。
·
学习视频
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 中的不可变数据)
- 需要完全隔离的配置副本
- 复杂数据结构的备份/恢复
六、性能优化技巧
- 按需深拷贝:只拷贝需要修改的部分属性
- Immutable.js:使用不可变数据结构库优化
- 结构化克隆:利用浏览器原生能力(兼容性要求)
// 浏览器API(需兼容性检查) const cloned = structuredClone(original);
通过理解深浅拷贝的机制,可以避免因引用共享导致的隐蔽 Bug,同时根据场景合理选择拷贝策略以平衡性能与安全性。
更多推荐
所有评论(0)