localStorage 详细介绍
localStorage 是 Web Storage API 的一部分,属于浏览器端持久化存储,用于在客户端(浏览器)保存键值对数据。同系列还有 sessionStorage,二者接口完全一致,仅生命周期不同。
注意:localStorage 存储在当前源(origin),协议+域名+端口三者必须完全相同才能读取,跨域隔离。
一、核心特性
- 持久化存储:数据不会随页面关闭而清除,除非手动调用API删除、清除浏览器缓存/网站数据。
- 仅字符串:所有存入的值都会被自动转字符串;对象/数组需要手动 JSON.stringify / JSON.parse。
- 容量限制:一般 5MB(每个源),超出会抛出
QuotaExceededError。 - 同步操作:读写是同步阻塞的,大量数据读写会阻塞JS主线程。
- 不会随HTTP请求发送:和 Cookie 最大区别,localStorage 不会自动带到后端请求头里。
- 同源策略隔离:
[http://a.com](http://a.com)和[https://a.com](https://a.com)、a.com和b.com互相不能访问。 - 只在浏览器环境可用:Node.js 没有原生 localStorage。
和 sessionStorage 对比
- localStorage:永久保存,手动删才消失
- sessionStorage:页面会话,标签页关闭就清空
二、API 方法(全部挂载在 window.localStorage)
1. 写入数据:setItem(key, value)
// 基础字符串
localStorage.setItem('username', 'zhangsan');
// 存对象/数组,必须序列化
const user = { name: 'lisi', age: 20 };
localStorage.setItem('user', JSON.stringify(user));
key 和 value 都只能是字符串。
2. 读取数据:getItem(key)
const name = localStorage.getItem('username');
// 读取对象要反序列化
const userStr = localStorage.getItem('user');
const user = userStr ? JSON.parse(userStr) : null;
找不到 key 返回 null
const name = localStorage.getItem('username');
// 读取对象要反序列化
const userStr = localStorage.getItem('user');
const user = userStr ? JSON.parse(userStr) : null;
3. 删除单条:removeItem(key)
localStorage.removeItem('username');
4. 清空全部:clear()
localStorage.clear();
清空当前源下所有 localStorage,慎用
localStorage.clear();
5. 获取索引key:key(index)
const len = localStorage.length;
for(let i = 0; i < len; i++){
const k = localStorage.key(i);
const v = localStorage.getItem(k);
console.log(k, v);
}
按下标获取 key 名称,配合 length 遍历
const len = localStorage.length;
for(let i = 0; i < len; i++){
const k = localStorage.key(i);
const v = localStorage.getItem(k);
console.log(k, v);
}
6. 获取存储数量:localStorage.length
返回当前源下存储的键值对个数。
三、两种读写写法(不推荐点语法)
// 这种语法也能读写,但不推荐!
localStorage.foo = "bar";
delete localStorage.foo;
问题:key 名如果是 setItem、getItem 这类内置属性名会冲突;无法捕获存储容量溢出异常。优先使用 setItem / getItem。
四、存储事件:storage
当其他标签页/窗口修改了 localStorage,当前页面会触发 storage 事件。
⚠️:当前页面修改 localStorage,不会触发自己页面的 storage 事件,只有同源的其他页面收到。
window.addEventListener('storage', (e) => {
console.log('发生变化:', e);
// e.key:变化的键;null代表clear()
// e.oldValue:旧值
// e.newValue:新值
// e.url:哪个页面修改的
// e.storageArea:localStorage对象
})
典型场景:多标签页登录状态同步。
五、常见坑 & 注意事项
- 只能存字符串
localStorage.setItem('num', 100);
console.log(localStorage.getItem('num')) // "100" 字符串
- JSON.parse 容错
function getLocal(key){
try {
const val = localStorage.getItem(key);
return val ? JSON.parse(val) : null;
} catch(e){
return null;
}
}
如果存储的数据损坏,直接 JSON.parse 会报错,建议 try-catch
function getLocal(key){
try {
const val = localStorage.getItem(key);
return val ? JSON.parse(val) : null;
} catch(e){
return null;
}
}
- 容量超限报错
try{
localStorage.setItem('bigData', hugeStr);
}catch(err){
if(err.name === 'QuotaExceededError'){
console.log('存储空间已满');
}
}
写入超过5MB会抛出 QuotaExceededError,需要 try catch 捕获
try{
localStorage.setItem('bigData', hugeStr);
}catch(err){
if(err.name === 'QuotaExceededError'){
console.log('存储空间已满');
}
}
- 隐私模式(无痕)
不同浏览器行为不一样:有的无痕模式下 localStorage 可用,关闭标签就清空;有的浏览器直接禁止写入。
- XSS 安全风险【重点】
localStorage 可以被页面内JS完全读取。
如果网站存在XSS漏洞,攻击者脚本可以拿到 localStorage 里所有数据。
不要把敏感凭证(token、密码)直接放在 localStorage!
建议:身份凭证优先 HttpOnly Cookie,防止XSS窃取。
- 同步阻塞
localStorage 读写是同步IO,大量数据读写会卡住页面渲染,大数据不要放localStorage,可以考虑 IndexedDB。
- 大小写敏感:
localStorage.setItem("A",1)和localStorage.setItem("a",2)是两个不同key。
六、localStorage vs Cookie vs sessionStorage vs IndexedDB
| 特性 | localStorage | Cookie | sessionStorage | IndexedDB |
|---|---|---|---|---|
| 存储大小 | ~5MB | ~4KB | ~5MB | 很大(几十MB+) |
| 生命周期 | 永久 | 可设置过期 | 标签关闭销毁 | 永久 |
| 随HTTP请求发送 | ❌ | ✅ | ❌ | ❌ |
| 读写 | 同步 | - | 同步 | 异步 |
| 数据类型 | 字符串 | 字符串 | 字符串 | 任意类型 |
| 跨标签通信 | storage事件 | 可 | 不可 | 可 |
| 安全 | 易XSS读取 | HttpOnly防XSS | 易XSS读取 | 易XSS读取 |
七、适用场景 & 不适用场景
✅ 适合:
- 保存非敏感用户偏好:主题设置、语言、表格列显示配置
- 本地缓存非敏感静态数据,减少接口请求
- 多标签页简单状态同步
❌ 不适合:
- 存储账号密码、登录密钥等敏感信息
- 大量二进制、大数据存储
- 需要服务端自动读取的身份凭证
- 需要事务、复杂查询的结构化数据
八、封装简易工具函数(可直接复制使用)
const Storage = {
set(key, value) {
try {
const data = JSON.stringify(value);
localStorage.setItem(key, data);
return true;
} catch (e) {
console.error('存储失败', e);
return false;
}
},
get(key) {
try {
const str = localStorage.getItem(key);
if (str === null) return null;
return JSON.parse(str);
} catch (e) {
console.error('读取失败', e);
return null;
}
},
remove(key) {
localStorage.removeItem(key);
},
clear() {
localStorage.clear();
}
}
如果你需要,我可以再补充:
- localStorage 容量检测代码
- storage事件实现多标签登录同步完整示例
- localStorage 持久化加密方案(规避XSS明文风险)
localStorage 存储容量能不能修改?
结论:不能通过 JS 代码修改,也不能在网站代码里配置扩容。
localStorage 的配额是浏览器层面固定限制(每个源 origin,约 5MB),网页脚本没有权限去修改这个上限。
一、详细说明
- 配额单位
5MB 指的是UTF-16 字符数量,不是字节(byte)。JS 字符串是 UTF-16,一个字符占 2 字节。
> 也就是说:5MB 配额 ≈ 2.5M 个字符。
> 存入中文、字母都按一个字符计数。
- 为什么前端代码无法修改
配额属于浏览器安全策略:- 防止单个网站无限占用用户磁盘;
- JS API 没有提供任何修改配额、申请更大容量的接口;
- 写入超过上限直接抛出
QuotaExceededError。
- 开发者本地能不能手动改?
✅ 可以(仅限本地调试,用户浏览器无法强制修改)- Chrome / Edge:可以启动浏览器时加命令行参数,临时修改 WebStorage 配额。
# Windows示例
chrome.exe --local-storage-quota=10485760
参数单位:字节,上面例子设置为10MB。
⚠️ 重要:这个只是本地调试用,普通用户不会去改,线上用户浏览器仍然是默认5MB。不能用于生产环境。
- 无痕模式下的特殊情况
无痕模式 localStorage 配额通常会更小,并且关闭窗口全部清空,同样无法由网页修改。
二、容量不够时的替代方案(生产可用)
| 方案 | 容量 | 读写 | 说明 |
|---|---|---|---|
| IndexedDB | 很大(一般剩余磁盘,有提示) | 异步 | 推荐,大数据本地存储首选 |
| Cache API | 较大 | 异步 | 主要用于缓存静态资源 |
| localStorage | ~5MB | 同步 | 只适合小配置、少量数据 |
补充:IndexedDB 也不是无上限,当存储量达到一定程度,浏览器会弹出提示询问用户是否允许更大存储。
三、判断当前剩余容量的简易代码
// 粗略估算localStorage剩余空间
function getLocalStorageQuota() {
const testKey = '__test_size__';
let str = '';
try {
while (true) {
str += 'a';
localStorage.setItem(testKey, str);
}
} catch (e) {
localStorage.removeItem(testKey);
// str.length 就是最大字符数
console.log('最大字符数:', str.length);
return str.length;
}
}
四、常见误区
❌ 误区1:meta标签、响应头可以设置 localStorage 容量
没有任何 HTTP 响应头、HTML meta 标签支持配置 localStorage 配额。
❌ 误区2:可以通过API申请扩容,类似IndexedDB
Web Storage(localStorage/sessionStorage)规范没有申请更大存储的API,IndexedDB才有存储权限申请机制。
如果你想,我可以写一段 IndexedDB 的简易封装,用来替代 localStorage 存储更大体量的数据。