再见`JSON.stringify()`和`{...obj}`,你好`structuredClone()`!
-
什么是
structuredClone()
?structuredClone()
是 2022 年引入的全局函数,支持 JavaScript 对象的深度克隆。与JSON.stringify()
和 等传统方法不同JSON.parse()
,它们难以应对复杂的结构和循环引用,而structuredClone()
可以轻松应对这些挑战。
-
为什么它会改变游戏规则?
- 它是一款强大的工具,可用于创建真正的深度克隆,无需额外的逻辑或变通方法即可保留嵌套对象和循环引用的完整性。此外,它还适用于现代环境,包括 Web Workers。
1. 简单对象克隆:基础知识
- 使用
{...obj}
(浅拷贝)
const original = { name: "Alice", details: { age: 25 } };
const shallowCopy = { ...original };
shallowCopy.details.age = 30;
console.log(original.details.age); // 30
console.log(shallowCopy.details.age); // 30
-
发生什么事了?
- 扩展运算符
{...obj}
仅创建浅拷贝。details
对象没有被深度克隆,因此更改也会shallowCopy.details
影响原始对象details
。 - 使用
JSON.stringify()
+JSON.parse()
(深层复制)
- 扩展运算符
const original = { name: "Alice", details: { age: 25 } };
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.details.age = 30;
console.log(original.details.age); // 25
console.log(deepCopy.details.age); // 30
-
发生什么事了?
- 此方法创建深层复制,但有局限性:它不能处理函数
undefined
或循环引用。 - 使用
structuredClone()
(深层复制)
- 此方法创建深层复制,但有局限性:它不能处理函数
const original = { name: "Alice", details: { age: 25 } };
const clone = structuredClone(original);
clone.details.age = 30;
console.log(original.details.age); // 25
console.log(clone.details.age); // 30
- 发生什么事了?
structuredClone()
创建深度克隆,保留结构而不受任何限制JSON.stringify()
,并处理复杂数据类型,如循环引用和undefined
。
2. 处理循环引用:一个挑战
- 循环引用
{...obj}
const original = { name: "Alice" };
original.self = original;
// This will cause an error:
const shallowCopy = { ...original }; // TypeError: Converting circular structure to JSON
-
发生什么事了?
{...obj}
无法处理循环引用,导致错误。- 循环引用
JSON.stringify()
const original = { name: "Alice" };
original.self = original;
// This will cause an error:
const jsonCopy = JSON.parse(JSON.stringify(original)); // TypeError: Converting circular structure to JSON
-
发生什么事了?
JSON.stringify()
循环引用也会失败,引发错误。- 循环引用
structuredClone()
const original = { name: "Alice" };
original.self = original;
const clone = structuredClone(original);
console.log(clone !== original); // true
console.log(clone.self === clone); // true
- 发生什么事了?
structuredClone()
无缝处理循环引用,创建适当的深度克隆而不会出现错误。
3. 使用函数进行克隆undefined
:另一个测试
- 使用
{...obj}
const original = { name: "Alice", greet: () => "Hello!", value: undefined };
const shallowCopy = { ...original };
console.log(shallowCopy.greet()); // "Hello!"
console.log(shallowCopy.value); // undefined
-
发生什么事了?
{...obj}
复制函数并按undefined
预期进行,但只是浅显的。- 使用
JSON.stringify()
const original = { name: "Alice", greet: () => "Hello!", value: undefined };
const jsonCopy = JSON.parse(JSON.stringify(original));
console.log(jsonCopy.greet); // undefined
console.log(jsonCopy.value); // undefined
-
发生什么事了?
JSON.stringify()
无法序列化函数或undefined
,导致它们在克隆对象中丢失。- 使用
structuredClone()
const original = { name: "Alice", greet: () => "Hello!", value: undefined };
const clone = structuredClone(original);
console.log(clone.greet); // undefined
console.log(clone.value); // undefined
- 发生什么事了?
structuredClone()
也不会克隆函数但会保留值,这使得它比复杂对象undefined
更可靠。JSON.stringify()
4. 速度与效率:性能说明
- 大数据效率
const largeArray = new Array(1e6).fill({ key: "value" });
console.time("structuredClone");
const clone = structuredClone(largeArray);
console.timeEnd("structuredClone");
console.time("JSON.stringify + JSON.parse");
const jsonCopy = JSON.parse(JSON.stringify(largeArray));
console.timeEnd("JSON.stringify + JSON.parse");
- 发生什么事了?
structuredClone()
对于大型复杂数据来说,通常比JSON.stringify()
+更快JSON.parse()
,并且避免了序列化和反序列化的陷阱。
5. 结论:structuredClone()
未来为何
- 可靠性
undefined
:更可预测地处理循环引用、函数和值。 - 效率:对大型数据集执行深度克隆的速度更快,并且不需要变通方法。
- 简单:一种方法即可解决所有问题 — — 不再需要在、或自定义深度克隆函数之间进行
{...obj}
选择JSON.stringify()
。