一、localStorage 是什么
-
浏览器提供的 键值对 持久化仓库,同源策略 隔离(协议+域名+端口三者一致才算同源)。
-
容量 :主流浏览器 5 MB 左右,超出抛
QuotaExceededError。 -
生命周期 :除非用户手动清缓存或代码
removeItem,否则永不过期。 -
同步 API :读写都阻塞主线程,高频大数据会掉帧。
-
仅支持字符串 :存对象必须先
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 做遍历 |
三、实战代码片段
-
对象存取封装
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; } } -
带过期时间(TTL)的升级版
javascriptfunction 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; } -
监听"别的标签页"对同一套数据的修改
=> 利用这个特性可以做"多标签页实时同步":购物车数量、主题切换、登录态踢下线等。
javascriptwindow.addEventListener('storage', (e) => { // 注意:本页面自己触发 setItem 不会触发该事件 console.log('key:', e.key); console.log('旧值:', e.oldValue); console.log('新值:', e.newValue); });四、容量检测与异常捕获
javascriptfunction 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
-
存敏感令牌(JWT、refresh_token)→ 易遭 XSS 直接读取,用
httpOnlyCookie 或内存。 -
存大量二进制(图片、文件)→ 5 MB 很快撑爆,用 IndexedDB。
-
需要"事务"或"索引查询"→ 用 IndexedDB。
-
需要"跨域共享"→ 做不到,同源策略限制。
-
需要"过期自动清理"→ 原生不支持,必须自己封装 TTL。
六、与 sessionStorage 的区别
-
localStorage:跨标签页、跨浏览器重启仍在。
-
sessionStorage :仅限同一标签页(包括 iframe),标签关闭即清空。
七、常见坑速览
-
iOS Safari 无痕模式 →
setItem直接抛错,必须try...catch降级。 -
浏览器隐私模式 → 有的返回
null但不抛错,也要做兼容性判断。 -
clear()会把当前域名下所有 key 清掉,别在公共库乱用。 -
不要高频写(如
mousemove),会卡渲染;需要"实时保存"用防抖/节流。