深拷贝在IndexedDB数据库读写过程中是怎么作为引擎底层默认行为自动执行的

小静君_3777

小静君_3777

2026-07-27

371人浏览

原创

indexeddb 不自动深拷贝,而是使用结构化克隆机制存取对象;该机制支持常见类型并处理循环引用,但不支持函数、symbol 等不可序列化值,也不调用自定义方法。

深拷贝在indexeddb数据库读写过程中是怎么作为引擎底层默认行为自动执行的

深拷贝并不是 IndexedDB 的底层默认行为,它完全不会自动执行。

IndexedDB 本身不负责、也不干预 JavaScript 对象的拷贝方式。当你把一个对象存入 IndexedDB(比如通过 store.add(obj)),浏览器会结构化克隆(structured cloning)该对象——这是一种由浏览器引擎实现的、比浅拷贝更深入、但又不等同于通用“深拷贝”的机制。

结构化克隆 ≠ 通用深拷贝

结构化克隆是 IndexedDB(以及 postMessage、localStorage(仅限字符串)、Cache API 等)所依赖的底层序列化协议,它的特点是:

  • ✅ 支持大多数常见类型:普通对象、数组、Date、RegExp、Map、Set、TypedArray、ArrayBuffer、Blob、File、ImageData
  • ✅ 自动处理循环引用(不会报错,能正确还原)
  • ✅ 保留原型链无关性(克隆后对象无 constructor 或原型方法)
  • ❌ 不支持函数、undefined、Symbol、Promise、WeakMap、WeakSet 等无法序列化的值(会直接丢弃或抛出 DataCloneError)
  • ❌ 不调用自定义 toJSON() 或 clone() 方法
  • ❌ 不等于 JSON.parse(JSON.stringify())(后者丢失 Date、RegExp、undefined、循环引用,且不能处理 Blob)

例如:

const original = {
  name: "Alice",
  born: new Date("2000-01-01"),
  scores: new Uint8Array([95, 87]),
  avatar: new Blob(["img-data"], { type: "image/png" })
};
// 存入 IndexedDB 后读出的对象,各字段被结构化克隆 —— 值相同,内存独立,但不是你写的“深拷贝函数”在运行

为什么容易误以为“IndexedDB 自动深拷贝”?

因为:

  • 你修改读出的对象,不会影响数据库里原始数据(✅ 表面看像深拷贝)
  • 你修改写入前的对象,也不会影响已存入的数据(✅ 数据已克隆隔离)
    但这只是结构化克隆的结果,不是 IndexedDB “调用了你的深拷贝逻辑”,更不是它内置了 Lodash.cloneDeep 这类行为。

实际开发中要注意什么?

  • 不要依赖 IndexedDB 来“帮你深拷贝任意对象”——遇到函数或 Symbol 就失败

  • 如果你需要存函数或特殊状态,得提前序列化(如转成字符串、保存元信息)

    Preqstation
    Preqstation

    一款AI工具,主要用于将PREQSTATION编码任务委派给Claude Code、Codex CLI或Gemini CLI,采用PTY安全执行(工作目录+后台+监控),适合需要提升相关任务效率的用户。

    下载
  • 从 IndexedDB 读出的数据,虽然与原数据内存隔离,但仍是只读视图(如 Blob、ArrayBuffer 可安全使用,但修改其内容不影响库内存储)

  • 若需对读出对象做进一步克隆(比如用于状态管理),应显式调用 structuredClone()(现代浏览器支持)或选用可靠深拷贝方案,而非假设 IndexedDB 已为你做完全部工作

  • structuredClone() 是目前最接近 IndexedDB 内部行为的 JS API,可用于手动复现该克隆逻辑

  • 使用 JSON.parse(JSON.stringify(x)) 存取复杂对象风险高,不推荐替代结构化克隆

  • 对含函数、私有字段、不可枚举属性的对象,必须自行设计序列化/反序列化策略

不复杂但容易忽略。

相关专题

更多
数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2023.06.29

2745

3

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2023.08.14

3941

10

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

2023.08.31

3011

3

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.05

967

5

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.09

2647

5

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

2023.10.16

2647

4

vb连接access数据库的方法
vb连接access数据库的方法

vb连接access数据库方法:1、使用ADO连接,首先导入System.Data.OleDb模块,然后定义一个连接字符串,接着创建一个OleDbConnection对象并使用Open() 方法打开连接;2、使用DAO连接,首先导入 Microsoft.Jet.OLEDB模块,然后定义一个连接字符串,接着创建一个JetConnection对象并使用Open()方法打开连接即可。

2023.10.16

2893

3

vb连接数据库的方法
vb连接数据库的方法

vb连接数据库的方法有使用ADO对象库、使用OLEDB数据提供程序、使用ODBC数据源等。详细介绍:1、使用ADO对象库方法,ADO是一种用于访问数据库的COM组件,可以通过ADO连接数据库并执行SQL语句。可以使用ADODB.Connection对象来建立与数据库的连接,然后使用ADODB.Recordset对象来执行查询和操作数据;2、使用OLEDB数据提供程序方法等等。

2023.10.19

2461

3

mdf文件导入数据库的方法
mdf文件导入数据库的方法

mdf文件导入数据库的方法有使用SQL Server Management Studio、使用SQL Server命令行工具、使用SQL Server Integration Services等方法。想了解更多mdf文件导入数据库的方法的相关内容,可以阅读本专题下面的文章。

2023.10.23

2653

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
php-src源码分析探索
php-src源码分析探索

共6课时 | 0.7万人学习

Golang云原生架构师课程
Golang云原生架构师课程

共49课时 | 4.8万人学习

Golang基础入门到精通(第二季)
Golang基础入门到精通(第二季)

共49课时 | 4.7万人学习