必须做序列化,因为localstorage只接受字符串类型;直接存对象会转为"[object object]"导致数据失效,json.stringify和json.parse是唯一合规路径,但存在序列化耗时、反序列化更慢及i/o阻塞三重性能损耗。

localStorage 本身不支持直接存对象或数组,所有非字符串数据都必须先转成字符串再写入,读取时再还原。这个“转来转去”的过程就是 JSON 序列化(JSON.stringify)和反序列化(JSON.parse),它看似简单,却是实际项目中最常被低估的性能瓶颈。
为什么必须做序列化?
localStorage 的 value 只接受字符串类型。当你执行 localStorage.setItem('user', {name: 'Alice'}),浏览器会自动调用对象的 .toString() 方法,结果存进去的是 "[object Object]" —— 这不是 bug,是规范行为。后续 JSON.parse("[object Object]") 直接报错,数据彻底失效。
只有显式用 JSON.stringify() 才能把对象变成合法 JSON 字符串;同理,只有 JSON.parse() 才能把它变回对象。这是绕不开的两步,但每一步都有隐性开销。
性能损耗主要来自哪几块?
损耗不是单一环节,而是三重叠加:
-
序列化耗时:对大型数组或嵌套深的对象,
JSON.stringify是 CPU 密集型操作。实测 10 万条简单字符串组成的数组,序列化可能耗时 40–80ms(尤其在低端安卓机上); -
反序列化更慢:
JSON.parse不仅要解析语法,还要构建新对象、分配内存,同等数据量下通常比 stringify 慢 1.2–1.5 倍; - I/O 阻塞主线程:localStorage 是同步 API,每次 setItem 或 getItem 都会阻塞渲染和 JS 执行,哪怕只是读一个键,如果磁盘响应稍慢(如旧设备、扩展插件干扰),就会卡住整个页面。
哪些情况会让损耗突然放大?
不是数据大才出问题,以下场景极易触发明显卡顿:
- 高频写入:比如实时保存编辑草稿,每敲几个字就
setItem一次,反复 stringify + I/O 累积延迟; - 大体积缓存:商品列表、历史记录、离线地图切片等,单条数据动辄几百 KB,一次存取就占掉几十毫秒;
- 错误兜底缺失:没加 try/catch 的
JSON.parse遇到损坏数据会直接抛错中断流程,用户感知就是“点不动了”; - 未判空直接 parse:
getItem返回null,JSON.parse(null)得到"null"字符串,后续逻辑全错乱。
怎么缓解这些损耗?
不一定要换技术栈,从使用方式入手就能显著改善:
- 批量合并写入:把多次小更新攒成一次大对象再存,减少调用次数;
- 读写分离策略:高频读取用内存缓存(如 Map 或变量),只在必要时(如页面卸载前)持久化到 localStorage;
- 轻量预校验:存之前用
typeof obj === 'object' && obj !== null判空,读之后先检查raw && raw.trim()再 parse; - 考虑替代方案:对 >1MB 或高并发场景,可评估 IndexedDB(支持异步、二进制、索引查询)或压缩后存(如使用 lz-string 压缩 JSON 字符串)。











