JavaScript 之 structuredClone 现代深拷贝
在 JavaScript 中,实现深拷贝的方式有很多种,每种方式都有其优点和缺点。今天介绍一种原生 JavaScript 提供的 structuredClone 实现深拷贝。
下面列举一些常见的方式,以及它们的代码示例和优缺点:
1. 使用 JSON.parse(JSON.stringify(obj))
代码示例:
优点:简单易行,对于大多数对象类型有效。
缺点:不能复制原型链,对于包含循环引用的对象可能出现问题。比如以下代码:
最终得到的 date 不是 Data 对象,而是字符串。
这是因为 JSON.stringify 只能处理基本的对象、数组。任何其他类型都没有按预期处理。例如,日期转换为字符串。Set/Map 只是转换为{}。
最终得到如下数据:
2. 使用递归
代码示例:
优点:对于任何类型的对象都有效,包括循环引用。
缺点:对于大型对象可能会消耗大量内存,并可能导致堆栈溢出。
3. 第三方库,如 lodash 的 _.cloneDeep 方法
代码示例:
优点:支持更多类型的对象和库,例如,支持 Proxy 对象。
缺点:会引入依赖导致项目体积增大。
因为这个函数会导致 17.4kb 的依赖引入,如果只是引入 lodash 会更高。
4. 现代深拷贝 structuredClone
在现代浏览器中,可以使用 structuredClone 方法来实现深拷贝,它是一种更高效、更安全的深拷贝方式。
以下是一个示例代码,演示如何使用 structuredClone 进行深拷贝:
structuredClone 可以做到:
拷贝无限嵌套的对象和数组
拷贝循环引用
拷贝各种各样的 JavaScript 类型,如 Date、Set、Map、Error、RegExp、ArrayBuffer、Blob、File、ImageData 等
哪些不能拷贝:
函数
DOM 节点
属性描述、setter 和 getter
对象原型链
所支持的完整列表:
Array、ArrayBuffer、Boolean、DataView、Date、Error 类型(下面具体列出的类型)、Map、Object,但仅限于普通对象、原始类型,除了 symbol(又名 number、string、null、undefined、boolean、BigInt)、RegExp、Set、TypedArray
Error 类型:
Error, EvalError, RangeError, ReferenceError , SyntaxError, TypeError, URIError
Web/API 类型:
AudioData, Blob, CryptoKey, DOMException, DOMMatrix, DOMMatrixReadOnly, DOMPoint, DomQuad, DomRect, File, FileList, FileSystemDirectoryHandle, FileSystemFileHandle, FileSystemHandle, ImageBitmap, ImageData, RTCCertificate, VideoFrame
值得庆幸的是 structuredClone 在所有主流浏览器中都受支持,也支持 Node.js 和 Deno。
最后
我们现在终于可以直接使用原生 JavaScript 中的 structuredClone 能力实现深度拷贝对象。每种方式都有其优缺点,具体使用方式取决于你的需求和目标对象的类型。
技术前沿拓展
前端开发,你的认知不能仅局限于技术内,需要发散思维了解技术圈的前沿知识。细心的人会发现,开发内部工具的过程中,大量的页面、场景、组件等在不断重复,这种重复造轮子的工作,浪费工程师的大量时间。
介绍一款程序员都应该知道的软件JNPF快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。
这是一个基于 Java Boot/.Net Core 构建的简单、跨平台快速开发框架。前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,实现快速开发,提升工作效率;框架集成了表单、报表、图表、大屏等各种常用的 Demo 方便直接使用;后端框架支持 Vue2、Vue3。如果你有闲暇时间,可以做个知识拓展。
看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~
评论