localstorage不能直接存对象,必须用json.stringify()转为字符串,否则存入“[object object]”导致解析失败;存取需判空+try/catch,防无效json、类型丢失与容量超限。

localStorage 不能直接存对象,必须用 JSON.stringify() 转成字符串;不这么做,存进去的就是 "[object Object]",取出来也还原不了原始结构。
为什么 localStorage.setItem("key", obj) 存的是 "[object Object]"
因为 localStorage.setItem() 的第二个参数会被强制调用 .toString()。对象默认的 toString() 返回就是 "[object Object]"——这不是 bug,是规范行为。
- 直接写
localStorage.setItem("user", {name: "Alice"})看似没报错,但查 DevTools → Application → Storage 就会发现值确实是字符串"[object Object]" - 后续
JSON.parse()会抛SyntaxError,因为"[object Object]"不是合法 JSON - 数字、布尔、
null会被转成对应字符串("42"、"true"、"null"),但数组和对象必须显式序列化
JSON.stringify() 静默丢数据的 4 种常见情况
它只处理可 JSON 序列化的类型:字符串、数字、布尔、null、普通对象、数组。其他一律被忽略或报错。
-
undefined字段直接消失:JSON.stringify({a: 1, b: undefined})→"{"a":1}" - 函数、
Symbol被跳过:JSON.stringify({fn: () => {}, sym: Symbol("x")})→"{}" -
Date实例变成 ISO 字符串,但读出来只是字符串,不是Date对象:JSON.stringify({ts: new Date()})→"{"ts":"2026-06-04T22:40:00.000Z"}" - 循环引用直接抛
TypeError: Converting circular structure to JSON,比如const a = {}; a.self = a;
安全存取对象的最小可用代码模板
绕过空值、损坏 JSON、类型丢失这三类高频问题,不依赖第三方库。
- 存的时候:
localStorage.setItem("user", JSON.stringify(user))(确保user是纯数据对象) - 取的时候必须判空 +
try/catch:const raw = localStorage.getItem("user");<br>let user = null;<br>if (raw) {<br> try {<br> user = JSON.parse(raw);<br> } catch (e) {<br> console.warn("localStorage user data is invalid JSON", e);<br> }<br>} - 如果需要保留
Date类型,存前转时间戳:{ ts: Date.now(), name: "test" },读出后手动new Date(parsed.ts)
多标签页同步和容量超限要额外防什么
storage 事件监听不到本页修改,QuotaExceededError 是同步错误,不兜住就中断脚本。
-
storage事件只在其他同源标签页触发变更时才派发,本页调用setItem()不会触发自己监听的该事件 - 存大对象前建议先估算长度:
new TextEncoder().encode(JSON.stringify(obj)).length,超过 4MB 就提前 warn 或分片 -
setItem()可能抛QuotaExceededError(尤其在 iOS Safari 或隐私模式下),必须包try/catch - 不要用
localStorage.clear()清空全部——误删其他模块 key 风险太高,优先用removeItem("key")
真正容易被忽略的不是“怎么存”,而是“谁动过它”:用户可能在 DevTools 里手改了值,其他脚本可能覆盖了同名 key,甚至浏览器扩展会注入干扰。所以每次 getItem() 后的 JSON.parse(),try/catch 不是可选项,是必选项。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











