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),会卡渲染;需要"实时保存"用防抖/节流。

相关推荐
weixin_382395237 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__7 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.8 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~9 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华9 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子12 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅12 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni12 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学13 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端