localstorage无统一容量上限,实际空间取决于浏览器、平台与系统状态;超限时setitem()抛出quotaexceedederror;需用textencoder计算utf-8字节长度并预留余量;应试探+异常捕获双保险;清理须按前缀、过期、损坏精准剔除;大数据应降级至indexeddb或分片存储。

浏览器对 localStorage 没有统一固定的容量上限,实际可用空间取决于浏览器类型、设备平台、隐私设置和系统状态。所谓“5MB”只是早期规范建议值,早已过时——Chrome 和 Edge 桌面版通常约 10 MB,Firefox 约 5–10 MB,而 iOS Safari 常低于 5 MB(内存紧张时可能骤降至 0),macOS Safari 17+ 已提升至 5 MB,但微信 X5 内核等 WebView 实测甚至不足 1 MB。超限时 setItem() 会抛出 QuotaExceededError,而非静默失败或截断。
真实字节数 ≠ 字符串长度
localStorage 按 UTF-8 字节计费,但 JavaScript 的 String.length 返回的是 UTF-16 编码的字符数。一个中文字符占 2 字节、一个 emoji(如 "?")占 4 字节,而 "?".length === 1。直接用 JSON.stringify(obj).length 估算必然高估空间。正确做法是:
- 用
new TextEncoder().encode(str).length获取真实 UTF-8 字节长度 - 注意 key 名、JSON 引号与空格也会占用字节,预估时需留出 10% 余量
- 避免对小数据(如单个开关)压缩,反而增加开销;建议 >2 KB 的数据才启用压缩
写入前轻量试探 + 异常捕获双保险
浏览器不提供 remainingSpace 这类 API,最可靠的方式是“先探路、再写入、失败即清理”:
- 写入前执行一次
localStorage.setItem('probe', 'x'),成功后立刻removeItem('probe') - 所有
setItem()必须包裹try-catch,专门捕获e.name === 'QuotaExceededError' - 捕获后触发清理逻辑,再重试本次写入,而不是丢弃数据
- 切忌依赖
localStorage.length或遍历所有 key 计算总长——它只返回项数,不反映字节总量
安全清理不能一刀切
清空全部数据(clear())会误删登录态、主题偏好、token 等关键字段。应按策略精准清理:
- 按命名前缀分类:只操作
cache_、draft_、search_等非核心 key - 优先删除过期项:读取 value 后尝试
JSON.parse,检查expiresAt或createdAt字段 - 自动剔除损坏项:解析失败的 value 很可能是脏数据,可安全移除
- 清理后建议校验关键字段是否存在,防止误操作影响核心功能
真正需要大容量时,换技术栈比硬扛更靠谱
localStorage 是同步、字符串-only、容量封顶的简易方案,不适合承载大数据。当单条数据超 100 KB 或总量逼近 5 MB 时,应主动降级:
- 首选 IndexedDB:异步、支持事务、配额可达磁盘空闲空间的 50–60%,单库轻松上 50 MB+
- 用 localForage 封装:API 与 localStorage 几乎一致,自动降级到 IndexedDB/WebSQL,老项目迁移成本低
- 临时数据改用
sessionStorage或内存 Map,页面关闭即释放 - 超 16 MB 的单条记录必须分片(
blobId_0、blobId_1…),否则 Chrome 直接拒绝写入











