首页 > 极客资料 博客日记
JavaScript 中 structuredClone 和 JSON.parse(JSON.stringify()) 克隆对象的区别
2024-09-06 11:00:05极客资料围观24次
这篇文章介绍了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. 语法
structuredClone(value)
structuredClone(value, { transfer })
2.2. 参数
- value:被克隆的对象
- transfer:可转移的数组
2.3. 返回值
返回值是原始值的深拷贝
2.4.
如果输入值的任一部分不可序列化,则抛出 DataCloneError
异常
3. 用法
3.1. 普通用法
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
是一个可转移对象的数组,里面的值并没有被克隆,而是被转移到被拷贝对象上
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. 示例
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);
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 详细信息可以看下下面的文章
1.2.3. 示例
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
兼容的数据结构,但在处理复杂数据类型或循环引用时有局限性- 两者都有限制,克隆的时候需要关注下克隆对象的数据类型再做选择
参考
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
相关文章
最新发布
- Nuxt.js 应用中的 prerender:routes 事件钩子详解
- 【问题解决】Tomcat由低于8版本升级到高版本使用Tomcat自带连接池报错无法找到表空间的问题
- 【FAQ】HarmonyOS SDK 闭源开放能力 —Vision Kit
- 六、Spring Boot集成Spring Security之前后分离认证流程最佳方案
- 《JVM第7课》堆区
- .NET 8 高性能跨平台图像处理库 ImageSharp
- 还在为慢速数据传输苦恼?Linux 零拷贝技术来帮你!
- 刚毕业,去做边缘业务,还有救吗?
- 如何避免 HttpClient 丢失请求头:通过 HttpRequestMessage 解决并优化
- 让性能提升56%的Vue3.5响应式重构之“版本计数”