JavaScript 中 structuredClone 和 JSON.parse(JSON.stringify()) 克隆对象的区别

JavaScript 中 structuredClone 和 JSON.parse(JSON.stringify()) 克隆对象的异同点

一、什么是 structuredClone?

1. structuredClone 的发展

structuredClone 是在 ECMAScript 2021(ES12)标准中引入的,ECMAScript 2021 规范正式发布于 2021 年 6 月

自 2022 年 3 月起,该功能适用于最新的设备和浏览器版本

Baseline 2022 Newly available

Since March 2022, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

2. structuredClone 的功能

2.1. 功能

全局的 structuredClone() 方法使用结构化克隆算法将给定的值进行深拷贝

2.2. 语法

javascript 复制代码
structuredClone(value)
structuredClone(value, { transfer })

2.2. 参数

  • value:被克隆的对象
  • transfer:可转移的数组

2.3. 返回值

返回值是原始值的深拷贝

2.4.

如果输入值的任一部分不可序列化,则抛出 DataCloneError 异常

3. 用法

3.1. 普通用法

javascript 复制代码
const obj = {
  name: '日升',
  sex: '男',
  blog: {
      csdn: 'https://guoqiankun.blog.csdn.net/?type=blog',
      jj: 'https://juejin.cn/user/2409752520033768/posts'
  },
  games: ['cf', '黑马喽', 'cs'],
  age: 18,
  bool: true,
  set: new Set([1,2,3]),
  map: new Map([['a', 'b'], ['c', 'd']]),
  null: null,
  und: undefined
}
const cloneObj = structuredClone(obj);

3.2. transfer 用法

transfer 是一个可转移对象的数组,里面的值并没有被克隆,而是被转移到被拷贝对象上

javascript 复制代码
const buffer = new ArrayBuffer(16);
console.log('buffer', buffer);
const cloned = structuredClone(buffer, { transfer: [buffer] });
console.log('buffer', buffer);
console.log('cloned', cloned);

二、structuredClone 和 JSON.parse(JSON.stringify()) 的区别

1. 支持的数据类型

从上面的示例中能看出,structuredClone 支持了很多中数据类型,基本类型和普通对象都支持

1.1. structuredClone

1.1.1. 支持的类型
  • 基本类型
  • 普通对象
  • Date 对象
  • RegExp 对象
  • Map
  • Set
  • ArrayBuffer
  • TypedArrays
  • Blob
  • File
  • ImageData
  • MessagePort
  • null、undefined
  • NaN、Infinity、-Infinity
  • 循环引用
1.1.2. 不支持的类型
  • 函数
  • symbol
  • WeakMap
  • WeakSet
  • HTMLElement
1.1.3. 示例
javascript 复制代码
const port1 = new MessageChannel().port1
const obj = {
  date: new Date(),
  regex: /test/i,
  map: new Map([['key1', 'value1'], ['key2', 'value2']]),
  set: new Set([1, 2, 3]),
  arrayBuffer: new ArrayBuffer(8),
  typedArray: new Uint8Array([1, 2, 3]),
  blob: new Blob(['Hello, world!'], { type: 'text/plain' }),
  file: new File(['file content'], 'filename.txt', { type: 'text/plain' }),
  imageData: (() => {
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    return context.createImageData(100, 100);
  })(),
  messagePort: port1,
  nullValue: null,
  undefinedValue: undefined,
  nanValue: NaN,
  infinityValue: Infinity,
  negativeInfinityValue: -Infinity,
  circularRef: {}
};

// 创建循环引用
obj.circularRef.self = obj;

// 克隆 obj 对象
const clonedObj = structuredClone(obj, {transfer: [port1]});

// 输出以验证
console.log(clonedObj);
javascript 复制代码
const obj = {
  func: function() { return "I'm a function"; },   // 函数
  symbol: Symbol('uniqueSymbol'),                  // Symbol
  weakMap: new WeakMap(),                          // WeakMap
  weakSet: new WeakSet(),                          // WeakSet
  element: document.createElement('div')           // HTMLElement
};

// 尝试克隆对象
try {
  const clonedObj = structuredClone(obj);
  console.log(clonedObj); // This line won't run if an error is thrown
} catch (error) {
  console.error('Error:', error); // DataCloneError: Failed to execute 'structuredClone'
}

1.2. JSON.parse(JSON.stringify())

1.2.1. 支持的类型
  • 数字
  • 字符串
  • 布尔值
  • 数组
  • 普通对象
1.2.2. 不支持的类型
  • Date、Map、Set、RegExp、Function、undefined、symbol、Infinity、NaN、循环引用...

JSON.stringify 详细信息可以看下下面的文章

【你需要了解的JSON.stringify()】

1.2.3. 示例
javascript 复制代码
JSON.parse(JSON.stringify({
  a: null,
  b: undefined,
  c: NaN,
  d: Infinity,
  e: () => ({}),
  f: new Map(),
  g: new Set(),
  h: Symbol('a'),
  i: Infinity
}))

// 返回值

{
  "a": null,
  "c": null,
  "d": null,
  "f": {},
  "g": {},
  "i": null
}

2. 循环引用

2.1. structuredClone

可以正确处理对象中的循环引用

2.2. JSON.parse(JSON.stringify)

如果对象中存在循环引用,调用 JSON.stringify 会抛出错误,导致克隆失败

3. 性能方面

3.1. structuredClone

通常在处理复杂对象时性能更优,特别是包含大量非 JSON 兼容类型的数据时,因为它是为深度克隆设计的原生方法,内部优化了许多复杂场景

3.2. JSON.parse(JSON.stringify)

在处理简单的、JSON 兼容的数据结构时可能性能较好,但在处理复杂对象或非 JSON 兼容类型时效率低下

4. 浏览器兼容

4.1. structuredClone

是一种较新的 API,在某些较旧的浏览器中不被支持

4.2. JSON.parse(JSON.stringify)

在现代浏览器和较旧的浏览器中都有广泛支持

三、总结

  • structuredClone 提供了更广泛的数据类型支持和对循环引用的处理能力,适用于复杂场景
  • JSON.parse(JSON.stringify) 适合处理简单、JSON 兼容的数据结构,但在处理复杂数据类型或循环引用时有局限性
  • 两者都有限制,克隆的时候需要关注下克隆对象的数据类型再做选择

参考

相关推荐
卋罖7501 分钟前
Razor 视图 + JavaScript + Vue/iView 组件实现的表格自定义列
javascript·vue·iview·razor视图
系统集成-鹰翔14 小时前
ERP图片改名后仍命中识别缓存:缓存键、十分钟到期与调用计数
javascript·经验分享·后端
FlyWIHTSKY16 小时前
vue2和vue3有什么区别,用法上有哪些区别
前端·javascript·vue.js
码云之上16 小时前
10 颗一模一样的「Edit」:中后台 Web Agent 怎么找到对的那一行
前端·人工智能·浏览器
程序员大阳17 小时前
副队长JavaScript教程(66)-本地存储实战:待办事项网页的开发
javascript·json·实战·待办事项·本地存储·案例
Dream-Y.ocean18 小时前
鸿蒙PC平台逻控 PLC 编辑器适配实战:基于 Electron 壳方案的纯 JavaScript 梯形图编程与仿真引擎开发
javascript·编辑器·harmonyos
前端小D20 小时前
JS核心底层
前端·javascript
Dovis(誓平步青云)21 小时前
启元 T1 Pro 人机相声搭档:语音-触摸双通道的启元机器人节奏引擎设计
开发语言·前端·javascript·microsoft·交互
codeejun1 天前
每日一Go·MySQL-11、覆盖索引 & 回表原理
javascript·数据库·mysql
用户298698530141 天前
React 前端将 Excel 工作表导出为图片的技术实践
javascript·react.js·excel