告别 JSON.parse(JSON.stringify()) — 原生深拷贝 structuredClone

深拷贝的老办法

在 JavaScript 中深拷贝一个对象,最常见的"hack"写法是:

js 复制代码
const copy = JSON.parse(JSON.stringify(original));

这个方法简单粗暴,但有一堆坑:

js 复制代码
const obj = {
  date: new Date(),
  regex: /test/gi,
  map: new Map([["key", "value"]]),
  set: new Set([1, 2, 3]),
  undef: undefined,
  fn: () => "hello",
  nan: NaN,
  infinity: Infinity,
};

const copy = JSON.parse(JSON.stringify(obj));
console.log(copy);
// {
//   date: "2026-02-11T06:00:00.000Z",  ← 变成了字符串
//   regex: {},                           ← 丢失了
//   map: {},                             ← 丢失了
//   set: {},                             ← 丢失了
//                                        ← undefined 直接消失
//                                        ← 函数直接消失
//   nan: null,                           ← 变成了 null
//   infinity: null                       ← 变成了 null
// }

还有一个致命问题 ------ 循环引用直接报错:

js 复制代码
const a = { name: "a" };
a.self = a;
JSON.parse(JSON.stringify(a)); // ❌ TypeError: Converting circular structure to JSON

structuredClone 登场

structuredClone() 是浏览器和 Node.js (v17+) 提供的原生深拷贝方法:

js 复制代码
const original = {
  date: new Date(),
  regex: /test/gi,
  map: new Map([["key", "value"]]),
  set: new Set([1, 2, 3]),
  nested: { deep: { value: 42 } },
  arr: [1, [2, [3]]],
};

const copy = structuredClone(original);

copy.nested.deep.value = 0;
console.log(original.nested.deep.value); // 42 ✅ 互不影响

copy.date instanceof Date; // true ✅ 类型保留
copy.regex instanceof RegExp; // true ✅
copy.map instanceof Map; // true ✅
copy.set instanceof Set; // true ✅

循环引用也能正确处理:

js 复制代码
const a = { name: "a" };
a.self = a;
const b = structuredClone(a); // ✅ 正常工作
b.self === b; // true(引用指向拷贝后的自身)

支持的类型

structuredClone 使用的是结构化克隆算法,支持绝大多数内置类型:

类型 JSON 方式 structuredClone
Date ❌ 变字符串 ✅
RegExp ❌ 变 {} ✅
Map / Set ❌ 变 {} ✅
ArrayBuffer ❌ ✅
undefined ❌ 丢失 ✅
NaN / Infinity ❌ 变 null ✅
循环引用 ❌ 报错 ✅

不支持什么

有几种东西是 structuredClone 无法克隆的:

js 复制代码
// ❌ 函数
structuredClone({ fn: () => {} });
// DOMException: () => {} could not be cloned.

// ❌ DOM 节点
structuredClone(document.body);

// ❌ 原型链(拷贝后丢失)
class Dog {
  bark() { return "woof"; }
}
const dog = new Dog();
const cloned = structuredClone(dog);
cloned instanceof Dog; // false
cloned.bark; // undefined

所以如果你的对象包含函数或需要保留原型链,structuredClone 不适用。

一个实用技巧:transferable objects

structuredClone 支持第二个参数 transfer,可以"移交"而不是"复制"某些对象(如 ArrayBuffer),避免内存翻倍:

js 复制代码
const buffer = new ArrayBuffer(1024 * 1024); // 1MB
const copy = structuredClone(buffer, { transfer: [buffer] });

console.log(buffer.byteLength); // 0 ← 原始的被清空了
console.log(copy.byteLength); // 1048576 ← 数据转移到了 copy

这在处理大型二进制数据时非常有用。

兼容性

  • Chrome 98+, Firefox 94+, Safari 15.4+, Node.js 17+
  • 2026 年的今天,基本可以放心使用

总结

场景 推荐方案
简单对象,无特殊类型 JSON.parse(JSON.stringify()) 仍然可用
包含 Date/Map/Set/循环引用 structuredClone()
需要保留原型链/函数 手写递归或 lodash _.cloneDeep()

以后深拷贝,先想想 structuredClone 吧。


原文链接:chenguangliang.com/posts/js-st...

相关推荐
Dream-Y.ocean1 小时前
鸿蒙PC平台宅匠 3D 室内设计适配实战:基于 Electron 壳方案的 Three.js 双渲染引擎与参数化户型编辑器开发
javascript·3d·harmonyos
Highcharts.js2 小时前
Highcharts Gantt使用符号的自定义数据标签开发甘特图示例
javascript·甘特图·highcharts·图表开发·实战代码·响应式图表
kyriewen5 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
工控丫丫6 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
Dream-Y.ocean9 小时前
鸿蒙PC平台星图遥感适配实战:基于 Electron 壳方案的纯 JavaScript 遥感图像处理引擎开发
javascript·electron·harmonyos
螺丝钉tina9 小时前
[Playwright ][16]Playwright + TypeScript API 自动化测试实战:API测试
前端·javascript·typescript
Highcharts.js11 小时前
React 中原生支持使用 JSX 组件配置自定义表格 Highcharts Grid
前端·javascript·react.js·前端框架·jsx·highcharts·自定义表格
Java后端的Ai之路11 小时前
【AIAgent开发】-Agent工具封装成CLI(纯干货!!!)
java·javascript·人工智能·agent·cli
薛定谔的猫-菜鸟程序员12 小时前
Electron开发超详细教程(从入门到放弃)
前端·javascript·electron