深拷贝 structuredClone 与 JSON 方法作用及比较

structuredClone 与 JSON.parse(JSON.stringify()) 方法

概述 两者都用于深拷贝对象,但存在重要差异:

  1. structuredClone() 现代浏览器 API,专为克隆设计 优势: ✅ 支持循环引用
javascript 复制代码
const obj = { name: "John" };
obj.self = obj;
const cloned = structuredClone(obj); // 正常工作

✅ 支持更多数据类型:

javascript 复制代码
Map、Set

Date(保持对象类型)

RegExp(保持对象类型)

ArrayBuffer、TypedArray

Blob、File

Error 类型(部分浏览器)

✅ 保持原型链(部分对象类型)

✅ 更高效(专门优化的算法)

限制: ❌ 不支持函数

❌ 不支持 DOM 节点

❌ 不支持 Symbol 属性

❌ IE 不支持

  1. JSON.parse(JSON.stringify()) 传统方法,通过 JSON 序列化实现

优势: ✅ 广泛兼容(包括旧浏览器)

✅ 简单易用

限制: ❌ 不支持循环引用

javascript 复制代码
javascript
const obj = { name: "John" };
obj.self = obj;
const cloned = JSON.parse(JSON.stringify(obj)); // 报错

❌ 数据类型丢失严重:

javascript 复制代码
Date → 字符串

Map/Set → 空对象 {}

RegExp → 空对象 {}

Function → 被移除

undefined → 被移除

NaN/Infinity → null

Symbol → 被移除

❌ 原型链丢失(全部变为普通对象)

性能对比

javascript 复制代码
// 基准测试示例
const obj = { /* 大型复杂对象 */ };

// structuredClone 通常更快
console.time('structuredClone');
structuredClone(obj);
console.timeEnd('structuredClone');

// JSON 方法较慢
console.time('JSON方法');
JSON.parse(JSON.stringify(obj));
console.timeEnd('JSON方法');

const original = {
  date: new Date(),
  set: new Set([1, 2, 3]),
  map: new Map([['a', 1]]),
  regex: /test/gi,
  fn: () => console.log('test'),
  undef: undefined,
  nan: NaN
};

// structuredClone
const clone1 = structuredClone(original);
console.log(clone1.date instanceof Date); // true
console.log(clone1.set instanceof Set); // true
// clone1.fn === undefined

// JSON 方法
const clone2 = JSON.parse(JSON.stringify(original));
console.log(typeof clone2.date); // "string"
console.log(clone2.set); // {}
console.log(clone2.fn); // undefined

选择建议 使用 structuredClone 当: 需要支持循环引用

需要保持特殊对象类型(Date、Map、Set等)

在现代浏览器/Node.js(≥17)环境中

处理复杂对象结构

使用 JSON 方法 当: 只需要简单的数据对象(无特殊类型)

不需要支持循环引用

需要兼容旧环境

明确知道对象只包含 JSON 安全的数据

其他替代方案:

javascript 复制代码
// 第三方库
import cloneDeep from 'lodash/cloneDeep';

// 自定义深拷贝函数
function deepClone(obj, hash = new WeakMap()) {
  // 处理循环引用和复杂类型
}

总结表格

特性 structuredClone JSON.parse(JSON.stringify())
循环引用 ✅ 支持 ❌ 报错(抛出 TypeError)
Date 对象 ✅ 保持 Date 类型 ❌ 转为 ISO 格式字符串
Map/Set ✅ 保持 Map/Set 类型 ❌ 转为空对象 {}
函数 ❌ 不支持(抛出 DOMException) ❌ 被移除
undefined ✅ 支持 ❌ 被移除
Symbol ❌ 不支持(抛出 DOMException) ❌ 被移除
原型链 ✅ 部分保持(仅限可克隆对象) ❌ 完全丢失
性能 ✅ 较优(原生实现) ❌ 较慢(需序列化和解析)
兼容性 现代浏览器(Chrome 98+、Firefox 94+) 所有浏览器(包括旧版 IE)

补充说明:

  1. 循环引用示例

    javascript 复制代码
    const obj = { name: "Alice" };
    obj.self = obj;
    structuredClone(obj); // 正常克隆
    JSON.stringify(obj); // 报错:Converting circular structure to JSON
  2. Date 对象处理差异

    javascript 复制代码
    const date = new Date();
    structuredClone(date) instanceof Date; // true
    JSON.parse(JSON.stringify(date)) instanceof Date; // false
  3. Map/Set 的特殊处理

    javascript 复制代码
    const map = new Map([["key", "value"]]);
    structuredClone(map) instanceof Map; // true
    JSON.parse(JSON.stringify(map)); // {}
  4. 性能对比场景

    • 对于 1MB 大小的对象:
      • structuredClone 耗时约 15ms
      • JSON 方法耗时约 35ms(含序列化和解析)
  5. 原型链保留范围

    • structuredClone 会保留内置对象(如 Array)的原型链
    • 自定义类的原型链会被扁平化为普通对象 推荐:在现代应用中使用 structuredClone(),为更复杂的场景准备备选方案。
相关推荐
QQ1__8115175154 小时前
Spring boot名城小区物业管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
钛态4 小时前
前端微前端架构:大项目的救命稻草还是自找麻烦?
前端·vue·react·web
一粒黑子4 小时前
【实战解析】阿里开源 PageAgent:纯前端 GUI Agent,一行JS让网页支持自然语言操控
前端·javascript·开源
独角鲸网络安全实验室4 小时前
2026微信小程序抓包全解析:从实操落地到合规风控,解锁前端调试新范式
前端·微信小程序·小程序·抓包·系统代理绕过·https证书严格校验·进程隔离
紫微AI4 小时前
前端文本测量成了卡死一切创新的最后瓶颈,pretext实现突破了
前端·人工智能·typescript
GISer_Jing4 小时前
AI前端(From豆包)
前端·aigc·ai编程
IT枫斗者4 小时前
前端部署后如何判断“页面是不是最新”?一套可落地的版本检测方案(适配 Vite/Vue/React/任意 SPA)
前端·javascript·vue.js·react.js·架构·bug
测试修炼手册4 小时前
[测试技术] 深入理解 JSON Web Token (JWT)
前端·json
AI老李4 小时前
2026 年 Web 前端开发的 8 个趋势!
前端
里欧跑得慢4 小时前
15. Web可访问性最佳实践:让每个用户都能平等访问
前端·css·flutter·web