JavaScript中深拷贝Map和Set需用迭代方法而非属性遍历,Map要递归深拷键值并新建实例,Set需逐项深拷元素;须处理循环引用(WeakMap缓存);现代推荐structuredClone(),支持Map/Set等但不支持Symbol键和函数。

JavaScript 中深拷贝 Map 和 Set 不能靠遍历属性或 for...in,因为它们的内部数据不暴露在对象属性上,也不在原型链中。必须用各自实例的迭代方法提取内容,再新建实例逐项克隆。
Map 的深拷贝:键和值都要递归处理
Map 的每个键和值都可能是任意类型——包括对象、Symbol、另一个 Map 或 Set,所以不能只拷贝引用,必须分别深拷贝键与值:
- 创建新的
Map实例 - 用
originalMap.forEach((value, key) => {...})或originalMap.entries()遍历所有键值对 - 对每个
key和value单独调用深拷贝函数(注意:键也可能是引用类型,比如对象或 Set) - 用
newMap.set(clonedKey, clonedValue)写入新 Map
Set 的深拷贝:逐项递归复制元素
Set 是无序唯一集合,没有键值概念,只需确保每个元素都被独立克隆:
- 创建新的
Set实例 - 用
originalSet.forEach(item => {...})或展开为数组[...originalSet]获取全部元素 - 对每个
item执行深拷贝(若 item 是对象或嵌套结构,不深拷贝会导致新 Set 仍指向原内存) - 用
newSet.add(clonedItem)添加到新 Set
必须考虑循环引用和特殊类型
如果 Map 或 Set 中包含循环引用(例如某个对象的属性又指向该 Map 自身),直接递归会栈溢出。解决方案是使用 WeakMap 缓存已处理过的对象,避免重复克隆:
立即学习“Java免费学习笔记(深入)”;
- 传入一个
cache = new WeakMap()作为参数记录映射关系 - 每次进入深拷贝前先查 cache,命中则直接返回缓存结果
- 新建实例后、填充数据前,先将原对象 → 新对象写入 cache
现代推荐方案:structuredClone()
Chrome 98+、Firefox 94+、Safari 15.4+ 已支持 structuredClone(),它原生支持 Map、Set、Date、RegExp、TypedArray 等,并自动处理循环引用:
- 语法简洁:
const cloned = structuredClone(originalMap) - Map 的键如果是对象或 Set,也会被完整克隆(注意:克隆后的键与原键不相等,
cloned.has(originalKey)为 false) - 不支持函数、Symbol 作为键、undefined 值,也不保留原型链;如需这些能力,仍需手写逻辑


















