无需登录 数据私有 本地保存

结构化克隆演示 - 深拷贝支持类型

11
0
0
0

结构化克隆演示

深入理解 structuredClone() 的深拷贝能力 —— 对比 JSON 序列化,直观查看支持与不支持的数据类型

循环引用 Map/Set Date/RegExp ArrayBuffer 函数 DOM节点
预设对象:
原始对象 original

      
structuredClone 结果 深拷贝

      
JSON 序列化结果 有损克隆

      
数据类型支持对照表
数据类型 structuredClone JSON 序列化 备注
String / Number / Boolean 支持 支持 基本类型,两者均完美支持
null / undefined 支持 部分 JSON 不支持 undefined(属性会被移除)
Object / Array 支持 支持 嵌套对象和数组均支持
Date 支持 丢失类型 JSON 将其转为字符串,丢失 Date 类型
RegExp 支持 丢失类型 JSON 将其转为空对象 {}
Map 支持 丢失类型 JSON 将其转为空对象 {}
Set 支持 丢失类型 JSON 将其转为空对象 {}
ArrayBuffer / TypedArray 支持 丢失类型 JSON 将其转为空对象或普通对象
Blob / File 支持 不支持 JSON 完全无法处理二进制数据
循环引用 支持 抛出错误 structuredClone 的核心优势
Function 抛出错误 忽略/错误 两者均不支持克隆函数
Symbol 抛出错误 忽略 Symbol 无法被克隆
DOM 节点 抛出错误 不支持 DOM 节点不可转移
WeakMap / WeakSet 不支持 不支持 弱引用集合不可克隆
代码示例
// 基本用法
const original = { name: 'Alice', data: new Map([['key', 42]]) };
const clone = structuredClone(original);

// 深拷贝验证:修改克隆不影响原对象
clone.name = 'Bob';
console.log(original.name); // 'Alice' — 未受影响 ✓

// 循环引用也能正确处理
original.self = original;
const clone2 = structuredClone(original); // 成功!JSON 会报错

// 不支持函数——会抛出 DOMException
try {
  structuredClone({ fn: function() {} });
} catch (e) {
  console.error(e.name); // 'DataCloneError'
}
常见问题 (FAQ)

structuredClone() 是 JavaScript 的原生全局函数,用于执行深拷贝(deep clone)操作。它基于浏览器的结构化克隆算法,最初为 Web Workers 的消息传递设计,现已公开为通用 API。

相比于 JSON.parse(JSON.stringify()),它能处理更多数据类型(如 Date、Map、Set、RegExp、ArrayBuffer、循环引用等),是现代前端开发中推荐的深拷贝方案。

核心区别:

  • 类型支持:structuredClone 支持 Date、Map、Set、RegExp、ArrayBuffer、Blob 等;JSON 仅支持基本类型、对象和数组。
  • 循环引用:structuredClone 能正确处理循环引用;JSON.stringify 会抛出 TypeError
  • undefined:structuredClone 保留 undefined 值;JSON 会移除 undefined 属性。
  • 函数/Symbol:两者均不支持,structuredClone 抛出 DataCloneError
  • 性能:对于大型对象,structuredClone 通常更快,因为它使用原生二进制序列化。

简单来说:structuredClone 是更强大、更可靠的深拷贝方案

完全支持:

  • 基本类型:String、Number、Boolean、null、undefined、BigInt
  • 对象和数组(包括嵌套、稀疏数组)
  • Date、RegExp
  • Map、Set
  • ArrayBuffer、TypedArray(Uint8Array 等)
  • Blob、File、FileList
  • ImageData、ImageBitmap
  • 循环引用结构

不支持:Function、Symbol、DOM 节点、WeakMap、WeakSet、Proxy、Error 对象的 stack 属性等。

查看上方对照表获取完整列表。

函数(Function)包含可执行代码和闭包上下文,无法被安全地序列化和反序列化。结构化克隆算法在底层使用二进制序列化,无法捕获函数的执行逻辑和词法环境。

如果需要传递行为,建议使用策略模式、配置对象或消息传递来替代直接克隆函数。如果确实需要深拷贝包含函数的对象,可以结合使用 structuredClone 和手动赋值函数属性。

可以!这是 structuredClone 相比 JSON 序列化的一个重要优势。结构化克隆算法内部维护了一个对象映射表,能够检测并正确处理循环引用,而不会陷入无限递归。

在上方演示中选择"循环引用"预设,即可直观看到 structuredClone 成功处理自引用对象,而 JSON 序列化会直接报错。

structuredClone() 在现代浏览器中得到广泛支持:

  • Chrome 98+(2022年2月)
  • Firefox 94+(2021年11月)
  • Safari 15.4+(2022年3月)
  • Edge 98+
  • Node.js 17+(使用 --experimental-global-structured-clone 标志),Node.js 18+ 默认支持

对于旧浏览器,可以使用 polyfill 或回退到 JSON.parse(JSON.stringify())(注意局限性)。

  • 原型链不会被保留:克隆后的对象是纯对象,原型链信息会丢失,只保留可枚举属性。
  • 只克隆可枚举属性:不可枚举属性、Symbol 键属性、getter/setter 不会被克隆。
  • RegExp 的 lastIndex:克隆后 lastIndex 会被重置为 0。
  • Error 对象:仅克隆可枚举属性(如 message),stack 可能不完整。
  • Transferable 对象:可以通过第二个参数转移(而非复制)ArrayBuffer 等可转移对象的所有权。

建议在使用前先测试目标对象是否包含不支持的类型,做好错误处理。

Node.js 18+ 版本已原生支持 structuredClone() 作为全局函数,无需任何额外配置。

Node.js 17 需要启动标志:node --experimental-global-structured-clone index.js

对于更早的 Node.js 版本,可以使用 v8 模块的序列化 API,或安装 @ungap/structured-clone polyfill。

示例:const clone = structuredClone(complexObject); — 用法与浏览器完全一致。