localStorage只能存字符串,对象需用JSON.stringify()序列化后存储,读取时用JSON.parse()解析,但需try-catch处理非法JSON;storage事件不触发本页变更。

localStorage只能存字符串,对象必须序列化
直接调用 localStorage.setItem('key', obj) 会把对象转成 [object Object] 存进去,取出来就完全不是原来的数据了。根本原因是 localStorage 的值只能是字符串类型,任何非字符串值都会被隐式调用 .toString() —— 对象就是那个空洞的字符串。
正确做法是手动序列化和反序列化:
- 存的时候用
JSON.stringify(obj) - 取的时候用
JSON.parse(str)
示例:
const user = { name: 'Alice', age: 30 };
localStorage.setItem('user', JSON.stringify(user));
// 取出后需解析
const saved = JSON.parse(localStorage.getItem('user'));
console.log(saved.name); // 'Alice'
JSON.stringify会丢掉函数、undefined、Symbol 和循环引用
如果你的对象里有方法、undefined 字段、Symbol 键,或者自身嵌套引用(比如 obj.parent = obj),JSON.stringify 会静默忽略它们,甚至直接报错(循环引用时)。
立即学习“前端免费学习笔记(深入)”;
常见踩坑场景:
- 存 Vue/React 组件实例或带方法的类实例 → 方法全丢失
- 存含
undefined的配置对象 → 该字段彻底消失 - 存从接口拿到的原始响应对象,但里面有个
circularRef→Uncaught TypeError: Converting circular structure to JSON
若必须保留函数或处理循环引用,得换方案:比如用 structuredClone(仅现代浏览器支持)配合 localStorage 外的持久化方式,或改用 sessionStorage + 内存缓存组合。
读取时务必加 try-catch,否则 JSON.parse可能崩溃
localStorage.getItem() 返回的是字符串或 null,但一旦存储内容被手动篡改(比如开发者工具里改成非法 JSON)、或之前存的是非 JSON 字符串(如纯数字 '42'),JSON.parse() 就会抛错,中断后续逻辑。
安全写法:
function getStoredObject(key) {
const str = localStorage.getItem(key);
if (!str) return null;
try {
return JSON.parse(str);
} catch (e) {
console.warn(`Failed to parse localStorage item "${key}":`, e);
return null;
}
}
别省略 try-catch,也别用 JSON.parse(str) || {} 这种写法——错误时会直接 throw,不会 fallback。
注意 storage 事件监听不到同页面的 setItem 变更
很多人想用 window.addEventListener('storage', handler) 监听自己页面改了 localStorage,结果发现没触发。这是因为该事件只在「其他同源窗口/标签页」调用 setItem 时才派发,当前页面的修改不会触发它。
如果需要响应本页数据变更,得手动通知:
- 封装一个
setStoredObject(key, obj)函数,在里面调用localStorage.setItem后再dispatchEvent(new Event('my-storage-change')) - 或者直接用状态管理(如
useState+ useEffect)配合本地存储同步
别依赖 storage 事件做本页响应,这是最常被误解的一点。



















