深拷贝含map/set的复杂数据结构需用structuredclone()(现代环境)或手写递归函数(兼容老环境),避免json方法丢失类型及浅拷贝失效;手动实现需用weakmap防循环引用,并分别处理map、set、数组、对象等类型。

JavaScript 中深拷贝包含 Map 和 Set 的复杂数据结构,不能依赖 JSON.parse(JSON.stringify())(它会丢弃 Map、Set、函数、undefined、Symbol 等),也不能只用浅拷贝(如展开运算符或 Object.assign)。需要手动递归处理这些内置集合类型。
使用结构化克隆(推荐:现代环境)
现代浏览器和 Node.js(v17.0+)已支持 structuredClone(),它原生支持 Map、Set、Date、RegExp、ArrayBuffer 等,且能保留引用关系(如循环引用):
const cloned = structuredClone(original)- 兼容性需检查:
typeof structuredClone === 'function' - 不支持函数、undefined、Symbol、Promise、DOM 节点等(但 Map/Set 完全 OK)
手写递归深拷贝(兼容老环境)
核心思路:对每个值判断类型,分别处理普通对象、数组、Map、Set、Date、RegExp 等,跳过不可枚举或原型属性:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 遇到
Map:新建Map,递归拷贝 key 和 value - 遇到
Set:新建Set,递归拷贝每个元素 - 遇到普通对象或数组:递归遍历属性/元素
- 基础类型(string/number/boolean/null)直接返回
- 用
WeakMap记录已拷贝的对象,防止循环引用死循环
示例片段:
function deepClone(obj, seen = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (seen.has(obj)) return seen.get(obj);
let cloned;
if (obj instanceof Map) {
cloned = new Map();
seen.set(obj, cloned);
for (const [k, v] of obj) {
cloned.set(deepClone(k, seen), deepClone(v, seen));
}
} else if (obj instanceof Set) {
cloned = new Set();
seen.set(obj, cloned);
for (const item of obj) {
cloned.add(deepClone(item, seen));
}
} else if (Array.isArray(obj)) {
cloned = [];
seen.set(obj, cloned);
obj.forEach((item, i) => cloned[i] = deepClone(item, seen));
} else {
cloned = {};
seen.set(obj, cloned);
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
cloned[key] = deepClone(obj[key], seen);
}
}
}
return cloned;
}
借助成熟库(快速落地)
如果项目已引入 Lodash 或其他工具库,可直接使用其健壮实现:
-
Lodash:
_.cloneDeep(value)—— 默认支持 Map/Set(v4.17.5+) - immer:适合需要“可变式写法”的场景,内部自动处理不可变拷贝
- 注意:部分轻量库(如 clone-deep)可能默认不支持 Map/Set,需查文档确认
注意事项与避坑点
实际使用中容易忽略的细节:
-
Map的 key 可以是任意类型(包括对象、函数、NaN),拷贝时 key 也要深拷贝(除非你明确希望 key 引用不变) -
Set中若含循环引用对象,必须用WeakMap缓存,否则栈溢出 - 自定义类实例不会被自动识别为
Map/Set,需额外判断obj.constructor === Map或用obj instanceof Map - Symbol 键在普通对象遍历中会被忽略,需用
Object.getOwnPropertySymbols()单独处理(如果需要)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










