返回
创建于
状态公开
深入理解 JavaScript 的 structuredClone
在前端开发中,我们经常遇到一个经典问题:如何安全地深拷贝一个对象?
过去我们可能会用 JSON.parse(JSON.stringify(obj)),也可能依赖 lodash.cloneDeep 这样的库。但这两种方式都有明显的局限:
- JSON 转换:丢失
Date、RegExp、Map/Set等特殊对象。 - 第三方库:额外的依赖,可能还带来性能开销。
好消息是,现代浏览器和 Node.js 已经提供了原生的深拷贝 API —— structuredClone。
什么是 structuredClone
structuredClone() 是一种 原生方法,可以创建任意 JavaScript 值的深拷贝。
语法非常简单:
1const clone = structuredClone(value);其中 value 可以是对象、数组、Map、Set,甚至是带循环引用的复杂结构。
支持的类型
相比传统 JSON 方法,structuredClone 支持的类型更广泛:
- 基本类型:string, number, boolean, null, undefined, BigInt, Symbol(作为对象属性值)
- 内建对象:Date, RegExp, Map, Set, ArrayBuffer, Blob, File, FileList, ImageData
- 循环引用:支持对象之间的自引用或互相引用
示例:
1const obj = {
2 name: "wenjie",
3 date: new Date(),
4 map: new Map([["a", 1]]),
5 set: new Set([1, 2, 3]),
6};
7
8const copy = structuredClone(obj);
9
10console.log(copy.date instanceof Date); // true
11console.log(copy.map.get("a")); // 1
12console.log(copy.set.has(2)); // true不支持的类型
某些值是不能被克隆的,比如:
- 函数(
Function) - DOM 节点
- 原型链信息(会丢失原型)
1const obj = {
2 fn: () => console.log("hello"),
3};
4
5structuredClone(obj);
6// ❌ 会抛错:function is not cloneable循环引用的处理
这是 structuredClone 的一大优势。过去遇到循环引用对象,JSON.stringify 会直接报错,而 structuredClone 可以正常工作:
1const a = {};
2a.self = a;
3
4const b = structuredClone(a);
5console.log(b.self === b); // true性能表现
官方实现基于 结构化克隆算法,底层是浏览器和 Node.js 的原生实现。 相较于 JSON 或第三方库:
- 对 复杂数据结构:速度更快,内存更高效
- 对 简单对象:差距不大,但可读性和安全性更好
兼容性
- 浏览器:Chrome 98+、Firefox 94+、Safari 15+
- Node.js:v17.0 起原生支持;v16.0 需要
--experimental标志
在老环境中,可以用 polyfill 或退回到 lodash.cloneDeep。
实战案例
-
深拷贝 Redux 状态
1const newState = structuredClone(oldState); -
Web Worker 数据传输
postMessage内部就用的结构化克隆算法,保证数据安全传递。 -
存储缓存
1const cache = structuredClone(data); 2localStorage.setItem("data", JSON.stringify(cache));
总结
structuredClone是现代 JS 环境下 最佳的深拷贝方案。- 支持更多类型,能处理循环引用,性能更优。
- 唯一要注意的是 不支持函数和 DOM 节点。
如果你还在用 JSON.parse(JSON.stringify(obj)),是时候升级了!