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

深拷贝并不是 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 就失败
如果你需要存函数或特殊状态,得提前序列化(如转成字符串、保存元信息)
从 IndexedDB 读出的数据,虽然与原数据内存隔离,但仍是只读视图(如 Blob、ArrayBuffer 可安全使用,但修改其内容不影响库内存储)
若需对读出对象做进一步克隆(比如用于状态管理),应显式调用
structuredClone()(现代浏览器支持)或选用可靠深拷贝方案,而非假设 IndexedDB 已为你做完全部工作structuredClone()是目前最接近 IndexedDB 内部行为的 JS API,可用于手动复现该克隆逻辑使用
JSON.parse(JSON.stringify(x))存取复杂对象风险高,不推荐替代结构化克隆对含函数、私有字段、不可枚举属性的对象,必须自行设计序列化/反序列化策略
不复杂但容易忽略。

















