浏览器原理 · 48/51
1. addEventListener 第三个参数 2. addEventListener 与 attachEvent 区别 3. 浏览器兼容性测试与内核 4. 浏览器兼容性问题 5. 浏览器内核与引擎 6. 浏览器图层创建条件 7. 浏览器多进程架构 8. 浏览器渲染机制 9. 浏览器存储方案 10. 浏览器版本检测方法 11. children 与 childNodes 区别 12. 常见浏览器兼容性问题 13. Chrome 页面进程数量 14. 坐标系统对比 15. 多标签页通讯方案 16. 删除 Cookie 17. 自定义事件 18. DOM 事件处理方式演进 19. 元素尺寸属性对比 20. DOM 节点操作 21. DOM 事件机制 22. addEventListener 与 attachEvent 的区别 23. 获取页面所有复选框 24. HTMLCollection 与 NodeList 区别 25. Hybrid 应用开发 26. 强缓存命中机制 27. 浏览器缓存机制 28. 页面编码与资源编码不一致处理 29. jQuery 事件绑定方法对比 30. Input 点击触发的事件顺序 31. JavaScript 浏览器兼容性问题 32. jQuery 多事件绑定实现 33. JSBridge 原理 34. 链接点击后 Hover 失效解决方案 35. 减少重绘和回流的性能优化 36. 移动端 300ms 点击延迟问题 37. 移动端视口配置 38. 移动端点击穿透问题解决 39. 移动端兼容性问题 40. JSBridge 原理与实现 41. 移动端 1px 像素问题解决方案 42. 浏览器渲染流程 43. 页面加载完成事件对比 44. Offset、Scroll、Client 属性对比 45. 同源策略与跨域解决方案 46. Script 标签位置对页面加载的影响 47. Service Worker 与 PWA 48. 存储方案对比:Cookie、Storage、IndexedDB 49. 强缓存默认时间 50. URL 到页面显示的完整过程 51. V8 引擎 JavaScript 执行过程

存储方案对比:Cookie、Storage、IndexedDB

对比浏览器四种存储方案的容量、API、跨域和自动发送特性

问题

对比 Cookie、localStorage、sessionStorage、IndexedDB 的区别,包括容量、API、跨域、自动发送等方面。

解答

特性对比表

特性CookielocalStoragesessionStorageIndexedDB
容量~4KB~5MB~5MB无限制(受磁盘限制)
生命周期可设置过期时间永久页面会话期间永久
自动发送每次请求自动携带
跨域同源 + path 限制同源同源同源
API字符串操作同步同步异步
数据类型字符串字符串字符串任意类型
// 设置 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 事件:可用于同源跨标签页通信