javascript本地存储如何实现_如何使用localStorage保存数据【教程】

localStorage只能存储字符串,存对象需用JSON.stringify序列化,取用JSON.parse解析;无自动过期,但可能被清空或超配额;同步阻塞主线程;

跨标签页需监听storage事件。

localStorage 不能存对象,直接 setItem 对象会变成 [object Object] —— 这是绝大多数人第一次踩的坑。

localStorage 只接受字符串,对象必须手动序列化

它底层只支持字符串键值对,任何非字符串类型(包括数字、布尔、nullundefined、对象、数组)都会被隐式转成字符串。比如 localStorage.setItem('count', 42) 实际存的是 "42";而 localStorage.setItem('user', {name: 'Alice'}) 存的是 "[object Object]",取出来就废了。

正确做法是显式用 JSON.stringifyJSON.parse

const user = { name: 'Alice', age: 30 };
localStorage.setItem('user', JSON.stringify(user));
// 取出时
const savedUser = JSON.parse(localStorage.getItem('user'));

注意:JSON.stringify 无法处理函数、undefinedDateRegExp、循环引用等,遇到这些要提前清洗或换方案(如 structuredClone + indexedDB)。

localStorage 没有过期机制,但可能被手动清空或超出配额

它不会自动过期,也不会因页面关闭而消失,但以下情况数据会丢失:

  • 用户手动清除浏览器缓存或“网站数据”
  • 调用了 localStorage.clear()localStorage.removeItem('key')
  • 存储超过浏览器限制(通常 5–10MB),此时 setItem 会抛出 QuotaExceededError

建议操作前加 try-catch:

try {
  localStorage.setItem('config', JSON.stringify(config));
} catch (e) {
  if (e.name === 'QuotaExceededError') {
    console.warn('localStorage 已满');
  }
}

localStorage 是同步阻塞的,大量数据会影响主线程

读写都发生在主线程,且是同步操作。如果存的是几 MB 的大字符串(比如未压缩的日志数组),getItem 可能卡住 UI 几百毫秒。

优化建议:

  • 只存必要字段,避免 dump 整个状态树
  • 高频更新场景改用内存缓存(Map 或变量),定时或节流后持久化
  • 超大结构考虑 indexedDB,它支持异步、二进制、索引查询

跨标签页监听数据变化要用 storage 事件

同一个域名下,一个标签页调用 setItem,其他同源标签页不会自动感知。必须主动监听 storage 事件:

window.addEventListener('storage', (e) => {
  if (e.key === 'theme') {
    document.documentElement.setAttribute('data-theme', e.newValue);
  }
});

注意:storage 事件在触发它的那个页面**不会**触发,只通知其他同源页面;e.oldValuee.newValue 都是字符串,且 e.url 是修改来源页面的完整 URL。

真正难搞的是:没有内置的“更新就刷新”机制,所有依赖 localStorage 的状态都要自己补监听逻辑——这点常被忽略,直到多窗口操作时数据不一致才暴露。