直接用 JSON.stringify 存本地存储会丢数据,需建立统一序列化代理层:encode 阶段将 Date、RegExp、Map、Set 转为带 $type 标记的普通对象,decode 阶段精准还原,普通类型零开销,嵌套时过滤不可序列化值,uni-app 中封装 safeSet/safeGet 并加前缀与错误兜底。

直接用 JSON.stringify 存本地存储(localStorage / uni.setStorageSync)会丢数据——Date 变字符串、RegExp 变空、Map/Set 直接消失,还不会报错。要真正“无损”,关键不是换库,而是建立一个**统一的数据序列化代理层**:它把高级类型先安全转成 JSON 可存的结构,读取时再精准还原。
统一序列化代理的核心逻辑
它本质是一个带双向转换能力的中间件:写入前 encode,读取后 decode。不侵入业务代码,所有存储操作都走这个代理,就能全局兜底。
- encode 阶段:识别
Date、RegExp、Map、Set等类型,转为带类型标记的普通对象(例如{ $type: 'Date', value: '2026-05-19T23:23:00.000Z' }) - decode 阶段:遇到这类标记对象,按规则重建原生实例(
new Date(value)、new RegExp(...)、new Map(...)等) - 对普通对象、数组、字符串、布尔等 JSON 原生支持类型,不做任何改动,保持零开销
支持 Map 和 Set 的关键细节
Map 和 Set 不能直接 JSON 化,但它们的键值对和元素可导出为数组。代理需做两件事:
- 存时:把
Map转成[[key1, val1], [key2, val2]]形式;Set转成[item1, item2]数组,并打上$type: 'Map'或$type: 'Set'标记 - 读时:检查标记,用
new Map(arr)或new Set(arr)还原,确保迭代顺序、引用行为与原始一致 - 注意嵌套:如果
Map的 key 是对象或函数(不可序列化),代理应提前过滤或抛错,避免静默失败
兼容 Date 和 RegExp 的安全写法
别只靠 .toString() 或 .toJSON(),它们丢失精度或标志位:
-
Date:用.toISOString()保证 UTC 一致性和可解析性;还原时用new Date(str),能正确处理时区 -
RegExp:必须同时保存.source和.flags(如/abc/gi的'abc'和'gi');还原时用new RegExp(source, flags),确保.test()、.exec()行为完全一致 - 避免用
re.toString(),它在某些正则中会漏掉u或y标志
在 uni-app 或 Vue 项目中快速落地
以 uni.setStorageSync 为例,封装一个带代理的存储函数:
- 定义
safeSet(key, data):内部调用你的 encode 函数 →JSON.stringify→uni.setStorageSync - 定义
safeGet(key, defaultValue = null):先uni.getStorageSync,再JSON.parse,最后用 decode 函数还原高级类型 - key 建议加统一前缀(如
'app-data:' + key),避免和其他模块冲突 - 读取时务必加 try/catch + 默认值兜底(如返回
[]而非null),防止首次运行或数据损坏导致白屏










