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

相关推荐
明月_清风13 分钟前
性能级目录同步:IntersectionObserver 实战
前端·javascript
明月_清风14 分钟前
告别暴力轮询:深度解锁浏览器“观察者家族”
前端·javascript
摸鱼的春哥18 分钟前
Agent教程17:LangChain的持久化和人工干预
前端·javascript·后端
程序员爱钓鱼2 小时前
Go操作Excel实战详解:github.com/xuri/excelize/v2
前端·后端·go
子兮曰10 小时前
async/await高级模式:async迭代器、错误边界与并发控制
前端·javascript·github
恋猫de小郭10 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
GIS之路12 小时前
ArcGIS Pro 中的 Notebooks 入门
前端
IT_陈寒14 小时前
React状态管理终极对决:Redux vs Context API谁更胜一筹?
前端·人工智能·后端
Kagol15 小时前
TinyVue 支持 Skills 啦!现在你可以让 AI 使用 TinyVue 组件搭建项目
前端·agent·ai编程
柳杉15 小时前
从零打造 AI 全球趋势监测大屏
前端·javascript·aigc