当前位置: 首页 > news >正文

JavaScript 中的 structuredClone() 如何彻底改变你的对象复制方式

当你需要一个对象的“完整”副本,包括所有嵌套层级,而不是仅仅一个引用时?今天,我们将深入探讨一个现代且强大的 JavaScript 特性:structuredClone(),它将彻底改变你处理深度复制的方式。

为什么复制对象会让人头疼?

在 JavaScript 中,当你复制基本类型(如数字、字符串)时,它们是按值传递的,这意味着你会得到一个独立的副本。但对于对象(包括数组),情况就不同了。简单的赋值操作(=)只会复制一个“引用”——一个指向内存中原始对象的指针。

let original = { name: "Alice", details: { age: 25 } };
let shallowCopy = original; // 浅层复制,只是复制了引用
shallowCopy.details.age = 30;
console.log(original.details.age); // 输出: 30!原始对象被修改了!

这被称为“浅层复制”,它会导致一个常见的问题:修改“副本”实际上会修改原始对象。这在处理复杂数据结构时尤其令人头疼,因为你可能会无意中修改了应用程序状态的关键部分。

过去的解决方案:JSON.parse(JSON.stringify())

structuredClone() 出现之前,开发者们常常使用一个技巧来实现深度复制:

let original = { name: "Alice", details: { age: 25 } };
let deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.details.age = 30;
console.log(original.details.age); // 输出: 25!原始对象未受影响。

这个方法通过将对象转换为 JSON 字符串,然后再解析回来,从而有效地打破了所有引用。对于简单的“普通旧数据”(POD)来说,它确实有效。

然而,这个方法有严重的局限性:

  • 函数和 **undefined** 丢失: 对象中的函数和值为 undefined 的属性在序列化过程中会直接消失。
  • 日期对象:Date 对象会变成字符串,失去其 Date 类型。
  • **Map**** 和 **Set**:** 这些强大的集合类型会变成空对象,数据完全丢失。
  • 循环引用会报错: 如果你的对象有循环引用(例如,obj.self = obj),JSON.stringify() 会直接抛出错误。
  • 类实例: 类的实例会变成普通对象,丢失原型链和方法。

显然,JSON.parse(JSON.stringify()) 远非一个完美的深度复制方案。

隆重登场:structuredClone()

为了解决这些长期存在的问题,JavaScript 引入了一个原生的、全局可用的方法:structuredClone()。这个方法基于浏览器内部用于在 Web Workers 之间传递数据的“结构化克隆算法”,因此它既强大又可靠。

structuredClone() 的主要目标是创建一个给定 JavaScript 值的深度克隆,并且它能处理许多 JSON.parse(JSON.stringify()) 无法处理的复杂情况。

基本语法:

const clone = structuredClone(value);
// 或者,如果你需要高级功能:
const clone = structuredClone(value, options);

structuredClone() 的超能力

  1. 无缝处理循环引用: 这是它最大的亮点之一!structuredClone() 可以正确地复制包含循环引用的对象,而不会抛出错误。
const original = { name: "MDN" };
original.itself = original; // 创建一个循环引用const clone = structuredClone(original);console.assert(clone !== original);     // true
console.assert(clone.itself === clone); // true (循环引用在克隆中得到保留)
  1. 支持更多数据类型:
    • MapSet:它们会正确地被克隆,保留所有数据。
    • DateDate 对象会作为有效的 Date 对象被克隆。
    • RegExp:正则表达式对象也会被正确克隆。
    • ArrayBufferSharedArrayBuffer 和类型化数组:这些二进制数据结构可以被克隆。
    • Error 对象:Error 对象及其子类也能被正确克隆。
    • undefined 值:不像 JSON.stringify()structuredClone() 会保留 undefined 属性。

性能优化:可转移对象 (transfer 选项)

structuredClone() 还有一个非常强大的可选参数 transfer。对于某些特殊对象(如 ArrayBuffer),你可以选择“转移”它们而不是克隆它们。这意味着底层数据资源的所有权会从原始对象转移到新对象,而不会在内存中进行复制。

这对于处理大型二进制数据(例如,在 Web Workers 中进行图像或音频处理)时,可以带来巨大的性能提升,因为它避免了昂贵的数据复制操作。

const largeBuffer = new ArrayBuffer(1024 * 1024 * 10); // 10MB 缓冲区
const originalObject = { buffer: largeBuffer };// 将缓冲区发送到 Web Worker,转移其所有权
// 注意:这里只是一个示例,实际应用中通常用于 postMessage
const clonedObject = structuredClone(originalObject, { transfer: [largeBuffer] });console.assert(originalObject.buffer.byteLength === 0); // 原始缓冲区现在被“中立化”(分离)
console.assert(clonedObject.buffer.byteLength === 1024 * 1024 * 10); // 克隆现在拥有该缓冲区

重要提示: 一旦对象被转移,原始对象就会变得“中立化”或“分离”,你将无法再访问其底层数据。

structuredClone() 不支持什么?

虽然 structuredClone() 非常强大,但它并非万能。它无法克隆那些具有运行时行为、闭包或与宿主环境(如浏览器 DOM)直接绑定的对象:

  • 函数 (**Function**): 包括箭头函数和类方法。函数本质上是行为,而不是纯数据,无法被克隆。
  • DOM 节点 (**HTMLElement**, **Document**): 这些是浏览器特有的对象,无法在不同的 JavaScript 领域之间复制。
  • 自定义类实例: 虽然它会克隆类实例的可枚举自有属性,但原型链、方法和不可枚举属性会丢失,结果会是一个普通对象,而不是原始类的实例。
  • WeakMapWeakSet
  • Promise
  • WindowglobalThis 对象。

如果尝试克隆这些不支持的类型,structuredClone() 会抛出 DataCloneError

实际用例

structuredClone() 在许多现代 JavaScript 应用中都非常有用:

  • 不可变状态管理: 在 React/Redux 等框架中,你可以使用 structuredClone() 安全地创建状态的深度副本,从而避免直接修改原始状态,确保数据流的可预测性。
  • 保存和恢复应用程序状态: 轻松创建游戏进度、用户表单或复杂 UI 配置的快照,以便保存和日后恢复。
  • 高效地将数据传输到 Web Workers: 利用 transfer 选项,以零复制开销将大型二进制数据传递给 Web Workers 进行后台处理。
  • 安全修改复杂配置: 在不影响原始配置对象的情况下,创建独立的配置副本进行临时修改。

浏览器兼容性

structuredClone() 已经在所有现代浏览器(Chrome、Firefox、Safari、Edge 等)和 Node.js 17+ 中得到了广泛支持。这意味着在大多数当代项目中,你都可以放心地使用它,而无需担心兼容性问题。

结论

structuredClone() 的出现是 JavaScript 在数据操作能力方面的一个重要里程碑。它提供了一个原生、健壮且高性能的深度克隆解决方案,有效地解决了 JSON.parse(JSON.stringify()) 等旧方法的局限性。

将其作为你在现代 JavaScript 环境中深度克隆对象和数组的默认方法吧!当然,也要记住它的局限性,并根据需要采取替代策略。掌握 structuredClone(),你就能更自信、更高效地处理复杂数据结构。

相关文章:

  • 制造业主要管理哪些主数据范围
  • 智能办公系统 — 审批管理模块 · 开发日志
  • 理解HTTP基本认证与表单登录认证
  • [创业之路-381]:企业战略管理案例分析-战略制定/设计-市场洞察“五看”:看宏观-经济-如何获得国家经济政策与愿景规划,以及技术发展趋势、技术成熟度
  • Windows 开始菜单快捷方式路径说明
  • Cygwin:在Windows上搭建类Linux环境的桥梁
  • 《红警2000》游戏信息
  • 工业级FPGA正在推进太空AI的基础设施建设
  • 前端面试热门知识点总结
  • Windows端的C函数setlocale、printf与wprintf打印中文字符谜局小解
  • 算法打卡第六天
  • C++:auto自动类型推导
  • 【算法】枚举右,维护左与滑动窗口对比理解(知识点详解提升思维)5.25
  • JAVA线程的几种状态
  • arxml文件
  • SpringBoot+MyBatis
  • 杠杆零件机械加工工艺规程设计与优化
  • 低功耗蓝牙BLE之LE Controller Package CRC校验
  • 9:OpenCV—模板匹配
  • Java面向对象 二
  • 怎样做免费网站推广/百度主页网址
  • 网站建设评审/网站视频
  • 沧州市建设服务中心网站/日本进口yamawa
  • 如何做微信网站建设/seo技巧分享
  • wordpress和betheme/安徽seo网络推广
  • 网站建设可行性分析表/免费百度下载