localStorage 和 sessionStorage 的核心区别在于作用域与持久性:localStorage 同源共享、持久存储,适合用户偏好;sessionStorage 仅限当前标签页、关闭即销毁,适合临时状态;二者均需手动 JSON 序列化存取并处理过期逻辑。

localStorage 和 sessionStorage 有什么区别?
关键看数据要不要跨标签页共享、要不要持久化。如果只是临时存当前页面用的数据,比如表单草稿、折叠状态,sessionStorage 更安全——关掉标签页就自动清空,不会污染其他会话。localStorage 则一直留着,适合用户偏好、主题设置这类需要“记住”的东西,但得自己处理过期逻辑。
常见错误:把敏感 token 存 localStorage,结果被 XSS 直接读走;或者误用 sessionStorage 想跨标签页同步登录态,发现拿不到。
-
localStorage同源下所有标签页共享,容量约 5–10MB,无自动过期 -
sessionStorage仅限当前标签页+其打开的子窗口,关闭即销毁 - 两者都只能存字符串,存对象必须
JSON.stringify(),取出来要JSON.parse()
怎么安全地存取 JSON 数据?
直接调 setItem 存对象会变成 [object Object],取出来是字符串不是对象——这是最常踩的坑。必须手动序列化和反序列化,而且得加 try/catch 防止解析失败(比如缓存被手动篡改过)。
function setJson(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch (e) {
console.error('localStorage write failed:', e);
}
}
function getJson(key) {
try {
const raw = localStorage.getItem(key);
return raw ? JSON.parse(raw) : null;
} catch (e) {
console.warn('localStorage parse failed for', key, e);
localStorage.removeItem(key); // 解析失败就删掉,避免下次再崩
return null;
}
}
注意:JSON.stringify() 会忽略函数、undefined、Symbol 和循环引用,别指望它能完整保留 JS 对象结构。
立即学习“Java免费学习笔记(深入)”;
如何给缓存加有效期?
浏览器原生不支持 TTL(time-to-live),得自己模拟。主流做法是在值里塞一个 expiresAt 时间戳,每次读取前比对当前时间。
function setWithExpiry(key, value, ttlMs) {
const item = {
value,
expiresAt: Date.now() + ttlMs
};
localStorage.setItem(key, JSON.stringify(item));
}
function getWithExpiry(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) return null;
try {
const item = JSON.parse(itemStr);
if (Date.now() > item.expiresAt) {
localStorage.removeItem(key);
return null;
}
return item.value;
} catch {
localStorage.removeItem(key);
return null;
}
}
- ttlMs 单位是毫秒,比如
1000 * 60 * 60表示 1 小时 - 不要依赖服务端时间,全用
Date.now(),避免时区或客户端时间不准的问题 - 过期检查只在读取时做,写入时不清理,否则频繁写会拖慢性能
大量数据或复杂查询怎么办?
localStorage 是纯键值对,没有索引、没有查询能力。如果要按字段筛选、分页、模糊搜索,硬靠 for...in 遍历所有 key 效率极低,还容易卡死 UI。
这时候该换方案了:
- 小量结构化数据(localStorage 存整个数组,读出来用
Array.filter()查 - 中量数据(100–1000 条):考虑
IndexedDB,支持事务、索引、游标遍历 - 需要全文搜索或离线 SQL:用
sql.js(WebAssembly 版 SQLite)或localForage封装层 - 纯前端 mock 接口:用
mock-service-worker拦截请求,把响应缓存到内存或localStorage
别为了省事把几百个用户订单全塞进 localStorage,查一条要遍历全部,用户点一下就卡两秒——这种体验问题往往比“多写几行代码”更值得优先解决。











