存储方案对比:Cookie、Storage、IndexedDB
对比浏览器四种存储方案的容量、API、跨域和自动发送特性
问题
对比 Cookie、localStorage、sessionStorage、IndexedDB 的区别,包括容量、API、跨域、自动发送等方面。
解答
特性对比表
| 特性 | Cookie | localStorage | sessionStorage | IndexedDB |
|---|---|---|---|---|
| 容量 | ~4KB | ~5MB | ~5MB | 无限制(受磁盘限制) |
| 生命周期 | 可设置过期时间 | 永久 | 页面会话期间 | 永久 |
| 自动发送 | 每次请求自动携带 | 否 | 否 | 否 |
| 跨域 | 同源 + path 限制 | 同源 | 同源 | 同源 |
| API | 字符串操作 | 同步 | 同步 | 异步 |
| 数据类型 | 字符串 | 字符串 | 字符串 | 任意类型 |
Cookie
// 设置 Cookie
document.cookie = 'username=john; max-age=3600; path=/; secure; samesite=strict';
// 读取所有 Cookie(返回字符串,需要自己解析)
console.log(document.cookie); // "username=john; token=abc"
// 解析 Cookie
function getCookie(name) {
const cookies = document.cookie.split('; ');
for (const cookie of cookies) {
const [key, value] = cookie.split('=');
if (key === name) return decodeURIComponent(value);
}
return null;
}
// 删除 Cookie(设置过期时间为过去)
document.cookie = 'username=; max-age=0';
localStorage / sessionStorage
// 存储
localStorage.setItem('user', JSON.stringify({ name: 'john', age: 25 }));
// 读取
const user = JSON.parse(localStorage.getItem('user'));
// 删除
localStorage.removeItem('user');
// 清空
localStorage.clear();
// 监听存储变化(跨标签页通信)
window.addEventListener('storage', (e) => {
console.log('Key:', e.key);
console.log('Old:', e.oldValue);
console.log('New:', e.newValue);
});
// sessionStorage API 完全相同,区别是关闭标签页后数据清除
sessionStorage.setItem('temp', 'data');
IndexedDB
// 打开数据库
const request = indexedDB.open('myDB', 1);
// 数据库升级(创建表结构)
request.onupgradeneeded = (e) => {
const db = e.target.result;
// 创建对象仓库(类似表),keyPath 是主键
const store = db.createObjectStore('users', { keyPath: 'id' });
// 创建索引
store.createIndex('name', 'name', { unique: false });
};
request.onsuccess = (e) => {
const db = e.target.result;
// 写入数据
const tx = db.transaction('users', 'readwrite');
const store = tx.objectStore('users');
store.add({ id: 1, name: 'john', age: 25 });
// 读取数据
const getRequest = store.get(1);
getRequest.onsuccess = () => {
console.log(getRequest.result);
};
};
// 封装 Promise 版本
function openDB(name, version) {
return new Promise((resolve, reject) => {
const request = indexedDB.open(name, version);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
使用场景
// Cookie:身份认证、服务端需要读取的数据
document.cookie = 'token=xxx; httpOnly; secure';
// localStorage:持久化配置、缓存数据
localStorage.setItem('theme', 'dark');
localStorage.setItem('cache_articles', JSON.stringify(articles));
// sessionStorage:表单临时数据、单次会话状态
sessionStorage.setItem('form_draft', JSON.stringify(formData));
sessionStorage.setItem('scroll_position', '500');
// IndexedDB:大量结构化数据、离线应用
// 适合存储:文件、图片 Blob、大型 JSON 数据集
关键点
- Cookie 会自动发送:每次 HTTP 请求都会携带,适合身份认证,但会增加请求体积
- Storage 是同步 API:大量数据操作会阻塞主线程,只能存字符串
- IndexedDB 是异步的:支持事务、索引、存储任意类型数据,适合大数据量场景
- sessionStorage 不跨标签页:即使同源,新开标签页也是独立的存储空间
- localStorage 的 storage 事件:可用于同源跨标签页通信
目录