什么是 structuredClone()?
structuredClone()
是 2022 年引入的全局函数,支持深度克隆 JavaScript 对象。与 JSON.stringify()
和 JSON.parse()
等传统方法不同,它们难以处理复杂的结构和循环引用,而 structuredClone()
可以毫不费力地处理这些挑战。
为什么它会改变游戏规则?
它是创建真正的深度克隆的强大工具,无需额外的逻辑或解决方法即可保持嵌套对象和循环引用的完整性。此外,它还可用于现代环境,包括 Web Workers。
1. 简单对象克隆:基础知识
- 使用
{...obj}
(浅拷贝)
javascript"> const original = { name: "Alice", details: { age: 25 } };const shallowCopy = { ...original };shallowCopy.details.age = 30;console.log(original.details.age); // 30console.log(shallowCopy.details.age); // 30
展开运算符 {...obj}
仅创建浅表副本。details
对象不是深度克隆的,因此对 shallowCopy.details
的更改也会影响原始详细信息
。
- 使用
JSON.stringify()
+JSON.parse()
(深拷贝)
javascript">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
此方法创建深层副本,但它有局限性:它无法处理函数、未定义
或循环引用。
- 使用
structuredClone()(
深拷贝)
javascript">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. 处理循环引用:一项挑战
- 带有
{...对象}
javascript">const original = { name: "Alice" };
original.self = original;// This will cause an error:
const shallowCopy = { ...original }; // TypeError: Converting circular structure to JSON
{...obj}
无法处理循环引用,从而导致错误。
- 使用
JSON.stringify()
的循环引用
javascript">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()
的循环引用
javascript">const original = { name: "Alice" };
original.self = original;const clone = structuredClone(original);console.log(clone !== original); // true
console.log(clone.self === clone); // true
structuredClone()
无缝处理循环引用,创建适当的深度克隆而不会出错。
3. 克隆 Functions 和 undefined
:另一个测试
- 使用
{...对象}
javascript">const original = { name: "Alice", greet: () => "Hello!", value: undefined };
const shallowCopy = { ...original };console.log(shallowCopy.greet()); // "Hello!"
console.log(shallowCopy.value); // undefined
{...obj}
按预期复制 functions 和 undefined
,但只是浅层复制。
- 使用
JSON.stringify()
javascript">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()
javascript">const original = { name: "Alice", greet: () => "Hello!", value: undefined };
const clone = structuredClone(original);console.log(clone.greet); // undefined
console.log(clone.value); // undefined
structuredClone()
也不会克隆函数,但会保留未定义的
值,因此对于复杂对象,它比 JSON.stringify()
更可靠。
4. 速度和效率:性能说明
大数据效率
javascript">const largeArray = new Array(1e6).fill({ key: "value" });// structuredClone: 161.200927734375 ms
console.time("structuredClone");
const clone = structuredClone(largeArray);
console.timeEnd("structuredClone");// JSON.stringify + JSON.parse: 690.014892578125 ms
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
()
是未来
- 可靠性:更可预测地处理循环引用、函数和
未定义的
值。 - 效率:更快地对大型数据集执行深度克隆,并且不需要解决方法。
- 简单性:一种方法可以统治所有 - 无需再在
{...obj}
、JSON.stringify()
或自定义深度克隆函数。