优秀的编程知识分享平台

网站首页 > 技术文章 正文

告别JSON.stringify,一行代码搞定JavaScript深拷贝的正确姿势!

nanyue 2025-06-10 17:04:45 技术文章 7 ℃

在JavaScript开发中,深拷贝是每个开发者都会遇到的需求。然而,许多开发者习惯使用的JSON.parse(JSON.stringify(obj))方法,却隐藏着诸多陷阱。今天,我们将深入探讨这种方法的缺陷,并介绍一种更可靠、更强大的替代方案——structuredClone。如果你还在为深拷贝问题烦恼,这篇文章绝对值得一读!

JSON.stringify的致命缺陷

JSON.parse(JSON.stringify(obj))虽然看起来简洁,但实际上却是一个充满问题的解决方案。以下是它无法正确处理的几种常见情况:

1.无法处理循环引用

const obj = { name: "对象" };
obj.self = obj; // 循环引用

// 抛出错误: TypeError: Converting circular structure to JSON
const copy = JSON.parse(JSON.stringify(obj));

一旦对象中存在循环引用,这种方法就会直接抛出错误,导致程序崩溃。

2.丢失特殊数据类型

JSON.stringify无法处理函数、Symbol、undefined,会将Date转为字符串,RegExp变为空对象,NaN和Infinity变为null。这意味着,如果你的对象中包含这些类型的数据,使用JSON.parse(JSON.stringify(obj))进行深拷贝时,这些数据将丢失或被错误处理。

3.原型链丢失

深拷贝后的对象变成了普通对象,失去了原型链上的所有方法和属性。这对于依赖原型链的代码来说,是一个巨大的问题。

4.Map、Set、WeakMap、WeakSet的处理

这些集合类型在JSON.stringify过程中都变成了空对象,数据完全丢失。这对于需要处理复杂数据结构的开发者来说,是无法接受的。

更可靠的深拷贝替代方案

既然JSON.stringify有这么多问题,那么有没有更好的替代方案呢?答案是肯定的。现代浏览器提供了原生的structuredClone API,它可以处理大多数情况,而且使用起来非常简单:

// 一行代码实现深拷贝
const copy = structuredClone(original);

优点

  • 支持循环引用structuredClone可以正确处理循环引用,不会导致程序崩溃。
  • 支持大多数内置类型:它支持Date、RegExp、Map、Set等内置类型,能够保留这些类型的原始结构。
  • 性能优于JSON方法:在性能方面,structuredClone也优于JSON.parse(JSON.stringify(obj))

缺点

  • 不支持函数、DOM节点、原型链:虽然structuredClone已经非常强大,但它仍然有一些限制。例如,它不支持函数、DOM节点和原型链。

实际案例对比

假设我们有一个包含多种数据类型的复杂对象:

const original = {
  name: "Kimi",
  age: 25,
  date: new Date(),
  regex: /kimi/g,
  map: new Map([["key1", "value1"]]),
  set: new Set([1, 2, 3]),
  symbol: Symbol("kimi"),
  undefinedValue: undefined,
  nanValue: NaN,
  infinityValue: Infinity,
  self: null
};

original.self = original; // 添加循环引用

使用JSON.parse(JSON.stringify(original))进行深拷贝时,会遇到以下问题:

  • 循环引用导致错误。
  • DateRegExpMapSet等类型的数据丢失或被错误处理。
  • SymbolundefinedNaNInfinity等特殊值丢失或被错误处理。

而使用structuredClone(original)进行深拷贝时,这些问题都能得到解决:

const copy = structuredClone(original);
console.log(copy); // 正确处理了所有数据类型,包括循环引用

为什么你应该选择structuredClone?

  • 可靠性structuredClone能够正确处理循环引用和多种内置类型,避免了JSON.stringify带来的诸多问题。
  • 性能:在性能测试中,structuredClone通常优于JSON.parse(JSON.stringify(obj))
  • 易用性:只需要一行代码,就能实现深拷贝,简单易用。

JSON.parse(JSON.stringify(obj))虽然简洁,但存在太多缺陷,不适合在实际项目中使用。相比之下,structuredClone作为现代浏览器提供的原生API,不仅能够处理循环引用和多种内置类型,而且性能更优。

最近发表
标签列表