javascript如何实现缓存_如何管理本地存储的数据

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 对象结构。

如何给缓存加有效期?

浏览器原生不支持 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,查一条要遍历全部,用户点一下就卡两秒——这种体验问题往往比“多写几行代码”更值得优先解决。