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

相关推荐
wearegogog1235 小时前
基于 MATLAB 的卡尔曼滤波器实现,用于消除噪声并估算信号
前端·算法·matlab
Drawing stars5 小时前
JAVA后端 前端 大模型应用 学习路线
java·前端·学习
品克缤5 小时前
Element UI MessageBox 增加第三个按钮(DOM Hack 方案)
前端·javascript·vue.js
小二·5 小时前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
小沐°6 小时前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
qq_419854056 小时前
CSS动效
前端·javascript·css
烛阴6 小时前
3D字体TextGeometry
前端·webgl·three.js
桜吹雪7 小时前
markstream-vue实战踩坑笔记
前端
C_心欲无痕7 小时前
nginx - 实现域名跳转的几种方式
运维·前端·nginx
花哥码天下7 小时前
恢复网站console.log的脚本
前端·javascript·vue.js