localStorage用法详解

一、localStorage 是什么

  1. 浏览器提供的 键值对 持久化仓库,同源策略 隔离(协议+域名+端口三者一致才算同源)。

  2. 容量 :主流浏览器 5 MB 左右,超出抛 QuotaExceededError

  3. 生命周期 :除非用户手动清缓存或代码 removeItem,否则永不过期

  4. 同步 API :读写都阻塞主线程,高频大数据会掉帧。

  5. 仅支持字符串 :存对象必须先 JSON.stringify,取回再 JSON.parse

二、5 个原生 API

接口 作用 示例 备注
setItem(key, value) localStorage.setItem('name','tom') value 只能是字符串
getItem(key) const v = localStorage.getItem('name') 无此 key 返回 null
removeItem(key) localStorage.removeItem('name') 静默忽略不存在的 key
clear() 清空 localStorage.clear() 清掉当前域名下所有键
key(index) 枚举 localStorage.key(0) 配合 length 做遍历

三、实战代码片段

  1. 对象存取封装

    javascript 复制代码
    // 写
    function setJson(k, obj) {
      try {
        localStorage.setItem(k, JSON.stringify(obj));
      } catch (e) {
        if (e.name === 'QuotaExceededError') {
          console.warn('localStorage 已满,自动清理旧数据再试');
          localStorage.clear();          // 粗暴方案,可按业务优化
          localStorage.setItem(k, JSON.stringify(obj));
        }
      }
    }
    
    // 读
    function getJson(k) {
      const raw = localStorage.getItem(k);
      if (!raw) return null;
      try {
        return JSON.parse(raw);
      } catch (e) {
        console.error('JSON 解析失败', e);
        return null;
      }
    }
  2. 带过期时间(TTL)的升级版

    javascript 复制代码
    function setWithTTL(k, obj, ttlMs) {
      const payload = { value: obj, exp: Date.now() + ttlMs };
      localStorage.setItem(k, JSON.stringify(payload));
    }
    
    function getWithTTL(k) {
      const raw = localStorage.getItem(k);
      if (!raw) return null;
      const { value, exp } = JSON.parse(raw);
      if (Date.now() > exp) {
        localStorage.removeItem(k);
        return null;
      }
      return value;
    }
  3. 监听"别的标签页"对同一套数据的修改

    => 利用这个特性可以做"多标签页实时同步":购物车数量、主题切换、登录态踢下线等。

    javascript 复制代码
    window.addEventListener('storage', (e) => {
      // 注意:本页面自己触发 setItem 不会触发该事件
      console.log('key:', e.key);
      console.log('旧值:', e.oldValue);
      console.log('新值:', e.newValue);
    });

    四、容量检测与异常捕获

    javascript 复制代码
    function usableSpace() {
      const testKey = '__test__';
      const testData = 'a'.repeat(1024 * 1024); // 1 MB
      let rem = 0;
      try {
        while (true) {
          localStorage.setItem(testKey, testData + localStorage.getItem(testKey));
          rem += 1;
        }
      } catch (e) {
        localStorage.removeItem(testKey);
        return rem; // 剩余可写 1 MB 块数
      }
    }
    console.log('大约还能写', usableSpace(), 'MB');

五、什么时候不要用 localStorage

  1. 存敏感令牌(JWT、refresh_token)→ 易遭 XSS 直接读取,用 httpOnly Cookie 或内存。

  2. 存大量二进制(图片、文件)→ 5 MB 很快撑爆,用 IndexedDB。

  3. 需要"事务"或"索引查询"→ 用 IndexedDB。

  4. 需要"跨域共享"→ 做不到,同源策略限制。

  5. 需要"过期自动清理"→ 原生不支持,必须自己封装 TTL。

六、与 sessionStorage 的区别

  • localStorage:跨标签页、跨浏览器重启仍在。

  • sessionStorage :仅限同一标签页(包括 iframe),标签关闭即清空。

七、常见坑速览

  • iOS Safari 无痕模式 → setItem 直接抛错,必须 try...catch 降级。

  • 浏览器隐私模式 → 有的返回 null 但不抛错,也要做兼容性判断。

  • clear() 会把当前域名下所有 key 清掉,别在公共库乱用。

  • 不要高频写(如 mousemove),会卡渲染;需要"实时保存"用防抖/节流。

相关推荐
永远是我的最爱1 小时前
基于.NET的小小便利店前台收银系统
前端·sqlserver·.net·visual studio
从文处安1 小时前
「九九八十一难」第一难:前端数据mock指南(TS + VUE)
前端
Zhencode2 小时前
Vue3 响应式依赖收集与更新之effect
前端·vue.js
x-cmd2 小时前
[x-cmd] jsoup 1.22.1 版本发布,引入 re2j 引擎,让 HTML 解析更安全高效
前端·安全·html·x-cmd·jsoup
天下代码客2 小时前
使用electronc框架调用dll动态链接库流程和避坑
前端·javascript·vue.js·electron·node.js
weixin199701080163 小时前
【性能提升300%】仿1688首页的Webpack优化全记录
前端·webpack·node.js
冰暮流星3 小时前
javascript之数组
java·前端·javascript
晚霞的不甘3 小时前
Flutter for OpenHarmony天气卡片应用:用枚举与动画打造沉浸式多城市天气浏览体验
前端·flutter·云原生·前端框架
xkxnq3 小时前
第五阶段:Vue3核心深度深挖(第74天)(Vue3计算属性进阶)
前端·javascript·vue.js
三小河3 小时前
Agent Skill与Rules的区别——以Cursor为例
前端·javascript·后端