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

相关推荐
We་ct1 分钟前
LeetCode 49. 字母异位词分组:经典哈希解法解析+易错点规避
前端·算法·leetcode·typescript·哈希算法
CHU7290353 分钟前
废品回收小程序前端功能设计逻辑与实践
前端·小程序
lzhdim4 分钟前
微星首款全白设计的M-ATX小板! MPG B850M EDGE TIMAX WIF刀锋 钛评测:性能媲美顶级X870E主板
前端·edge
恋猫de小郭8 分钟前
小米 HyperOS 4 大变样?核心应用以 Rust / Flutter 重写,不兼容老系统
android·前端·人工智能·flutter·ios
李火火的安全圈14 分钟前
基于Yakit、Wavely实现CVE-2025-55182(React Server Components(RSC)) 反序列化漏洞挖掘和POC编写
前端·react.js
Orange_sparkle25 分钟前
dify的web页面如何传入user用户信息进行对话,而不是uuid
前端·人工智能
Amumu1213833 分钟前
Vue Router 和 常用组件库
前端·javascript·vue.js
霍理迪38 分钟前
CSS移动端开发及less使用方法
前端·css
2601_9498574338 分钟前
Flutter for OpenHarmony Web开发助手App实战:HTML参考
前端·flutter·html
爱内卷的学霸一枚42 分钟前
现代前端工程化实践:从Vue到React的架构演进与性能优化(7000字深度解析)
前端·vue.js·react.js