structuredclone()能正确深拷贝map、set、date、regexp、arraybuffer、typedarray、bigint、error(部分环境)及循环引用;不支持函数、symbol、undefined(对象中跳过)、dom节点、weakmap/weakset、getter/setter等。

JavaScript 中用 structuredClone() 实现复杂引用类型的彻底深拷贝,是目前最简洁、原生、安全的方式——它能正确处理 Map、Set、Date、RegExp、ArrayBuffer、TypedArray、BigInt、Error(部分环境)、嵌套对象/数组,甚至循环引用(现代浏览器已支持)。
哪些复杂类型能被 structuredClone 正确深拷贝
structuredClone() 不是“万能”,但覆盖了绝大多数实际场景中的复杂引用类型:
-
集合类:
Map、Set(键值对、元素顺序、原型链均保留) -
时间与正则:
Date(拷贝时间戳)、RegExp(拷贝标志和模式) -
二进制与数值扩展:
ArrayBuffer、Uint8Array等所有TypedArray、BigInt - 嵌套结构:含上述类型的多层对象、数组(包括空槽、稀疏数组)
- 循环引用:Chrome 98+、Firefox 101+、Safari 16.4+ 已支持自动识别并重建引用关系
不能拷贝的类型和常见陷阱
它遵循 HTML 结构化克隆算法规范,因此明确排除以下类型:
-
函数(
function、async function、箭头函数)→ 抛出DataCloneError - Symbol → 被忽略(不会出现在克隆结果中)
-
undefined → 在对象属性中会被跳过;在数组中变成
undefined元素(但不丢失位置) -
DOM 节点(
Element、Document等)→ 不支持,抛错 - WeakMap / WeakSet → 无法序列化,不支持
- 带有自定义 getter/setter 或不可枚举属性的对象 → 只拷贝可枚举自有属性的值,不保留访问器或属性描述符
基本用法和错误处理建议
调用简单,但生产环境务必加 try...catch:
try {
const original = {
map: new Map([['a', 1], ['b', { x: 2 }]]),
set: new Set([1, 'hello']),
date: new Date('2023-01-01'),
buffer: new ArrayBuffer(8)
};
const clone = structuredClone(original);
console.log(clone.map.get('a')); // 1
console.log(clone.map === original.map); // false
} catch (err) {
if (err.name === 'DataCloneError') {
console.error('遇到不可克隆的值(如函数、Symbol、DOM节点等)');
}
}
替代方案对比:为什么不用 JSON.parse(JSON.stringify()) 或 Lodash
对比其他常用方式,structuredClone 的优势明显:
-
JSON 方法:丢弃
Date(变字符串)、undefined、Function、RegExp、NaN、Infinity、BigInt、Map/Set,且无法处理循环引用 -
Lodash _.cloneDeep:功能强但体积大(约 70KB),需引入依赖;对
ArrayBuffer、Transferable类型支持有限;不处理跨线程场景 -
structuredClone:浏览器/Node.js(v17.0+ 启用
--experimental-structured-cloning,v18.13+ 默认启用)原生支持;零依赖;性能好;语义标准;支持Transferable(配合postMessage高效传大对象)
不复杂但容易忽略:检查运行时是否支持,再 fallback(如仅需兼容老环境才引入 polyfill 或降级逻辑)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











