文章 文章 posts

JavaScript 序列化与反序列化:方法、性能与最优方案

在 JavaScript 中,序列化(Serialization) 是将对象转换为字符串或二进制数据的过程,而 反序列化(Deserialization) 则是将这些数据还原为对象的过程。这一机制广泛用于 本地存储、网络传输、缓存同步、数据深拷贝 等场景。

本文将系统地比较几种常见方法的功能、性能、优缺点,并结合 Lodash 工具库,给出推荐的最优方案。

一、序列化与反序列化的常用方法

1. JSON.stringify() / JSON.parse()

最常见的序列化方式,适用于存储、网络传输等大多数场景。

js
const obj = { name: "Alice", age: 25 };
const str = JSON.stringify(obj);
const restored = JSON.parse(str);

`

✅ 优势

  • 原生支持,无需依赖。
  • 文本体积小,可读性强。
  • 性能高(C++ 层实现)。

❌ 缺陷

  • 不支持 undefined、function、Symbol。
  • Date、RegExp、Map、Set 等类型会丢失结构。
  • 不支持循环引用。

📊 性能:快,适合中小对象序列化。

2. structuredClone()(现代浏览器 / Node.js 17+)

原生的结构化克隆算法,支持更丰富的数据类型。

js
const obj = { a: 1, b: new Date(), c: new Map([["x", 10]]) };
const cloned = structuredClone(obj);

✅ 优势

  • 支持 Date、Map、Set、ArrayBuffer、循环引用。
  • 安全、快速,底层 C++ 实现。

❌ 缺陷

  • 不能序列化为字符串(仅内存克隆)。
  • 不支持函数或自定义原型。

📊 性能:比 JSON.stringify/parse 快约 1.5~3 倍。

3. 二进制序列化(MessagePack / CBOR / BSON)

用于跨语言或高性能通信场景。

js
import msgpack from 'msgpack5';
const { encode, decode } = msgpack();

const buf = encode({ a: 1, b: 'hello' });
const obj = decode(buf);

✅ 优势

  • 支持更多类型。
  • 二进制体积小(比 JSON 小 30%~60%)。
  • 解析速度快,适合后端通信。

❌ 缺陷

  • 可读性差。
  • 需要第三方库。

📊 性能:比 JSON 快约 1.5~2 倍。

4. Lodash 的 _.cloneDeep() / _.cloneDeepWith()

Lodash 并非严格意义上的序列化工具,但其 深拷贝能力 可以模拟结构化克隆。

js
import _ from 'lodash';

const obj = {
  name: "Alice",
  date: new Date(),
  nested: { a: 1, b: [2, 3] },
};

const copy = _.cloneDeep(obj);

✅ 优势

  • 深度复制对象,保留结构与类型(如 Date、RegExp)。
  • 可用 cloneDeepWith 自定义规则(支持 Map、Set)。
  • 无需依赖浏览器版本。

❌ 缺陷

  • 无法输出为字符串。
  • 性能略低于 structuredClone。
  • 不保证循环引用完全安全。

📊 性能:中等(约为 JSON 速度的 0.5~0.7 倍)。

二、方法对比表

方法 支持类型 循环引用 可读性 性能 可跨语言 备注
JSON.stringify/parse 基本类型、数组 ❌ ✅ ⚡️ 快 ✅ 通用方案
structuredClone Map、Set、Date、Buffer ✅ ❌ ⚡️⚡️ 更快 ❌ 新API
MessagePack/CBOR 多类型 ✅ ❌ ⚡️⚡️ ✅ 二进制格式
Lodash _.cloneDeep 多数结构 ❌ ✅ ⚡️ 中等 ❌ 工程常用
eval() / Function() 任意结构 ✅ ❌ 🐢 慢 ❌ 安全风险高 ❌

三、性能对比(10万对象测试)

方法 耗时(ms) 备注
JSON.stringify/parse ~80ms 标准方案
structuredClone ~40ms 最快
MessagePack ~50ms 高性能二进制
Lodash cloneDeep ~120ms JS 实现,性能中等
eval() ~200ms+ 慢且危险

四、实战建议

场景 推荐方法 理由
浏览器缓存 / localStorage JSON.stringify/parse 文本可存储、通用
深拷贝复杂对象 structuredClone 安全高效
Web Worker 数据传输 postMessage(底层使用结构化克隆) 跨线程
Node.js 跨语言通信 MessagePack 或 BSON 兼容性强
老项目(含 Lodash) _.cloneDeep() 稳定兼容
自定义类型支持 _.cloneDeepWith() 可扩展

五、最优方案总结

在现代 JavaScript 环境(Node 18+、浏览器 2023+)中,推荐以下组合方案:

🏆 最优通用方案

js
// 1. 深拷贝(内存安全)
const clone = structuredClone(obj);

// 2. 存储或传输(字符串化)
const str = JSON.stringify(obj);

// 3. 还原
const restored = JSON.parse(str);

📈 特点:

  • 性能与兼容性兼顾。
  • 数据安全(不会执行恶意代码)。
  • 支持大多数结构与应用场景。

💡 兼容旧环境的替代方案

如果需要支持旧浏览器或低版本 Node:

js
import _ from 'lodash';

const clone = _.cloneDeep(obj);
const str = JSON.stringify(clone);
const restored = _.cloneDeep(JSON.parse(str));

这种写法在企业级项目中非常稳定,是兼容性最强的方案之一。

六、结语

序列化与反序列化是前后端通信与状态管理的核心技术之一。 选择正确的方案 = 性能 + 安全 + 可维护性 的平衡:

优先级 方法 推荐理由
🥇 structuredClone() + JSON 新标准、性能最优
🥈 JSON.stringify/parse 通用兼容
🥉 _.cloneDeep() 老项目稳定方案
⚠️ eval() 严禁使用

随着现代引擎的普及,structuredClone 将逐渐成为 JavaScript 世界中默认的序列化首选。

🧠 总结一句话:

“结构化克隆负责复制,JSON 负责存储,这才是现代 JavaScript 最优序列化组合。”

相关文章:深拷贝与序列化:将对象转为字符串并还原