标准答案

  1. Cookie 容量小,会按域名、路径和 SameSite 等规则随 HTTP 请求自动发送,适合保存会话标识、CSRF 相关标记和少量服务端必须读取的信息。安全属性要关注 HttpOnly、Secure、SameSite、Expires/Max-Age。
  2. localStorage 持久保存在同源下,容量通常比 Cookie 大,但 API 是同步的,只能直接存字符串,适合少量非敏感偏好配置、开关状态和本地 UI 设置。
  3. sessionStorage 只在当前标签页会话内有效,标签页关闭后清除。它适合临时表单状态、一次性跳转参数和不希望跨标签页共享的数据。
  4. IndexedDB 是浏览器端异步数据库,容量更大,支持结构化数据、索引和事务,适合离线缓存、大量列表数据、草稿箱和客户端数据库。敏感 token 不应随意放在 localStorage,一旦同源脚本被 XSS 控制就可能被读取。

题目解析

选择存储方案时先问四件事:服务端是否要自动收到、数据要活多久、数据量有多大、同源脚本能不能读取。Cookie 和 localStorage 最大的区别不是容量,而是 Cookie 会进入请求链路。

Cookie 的 HttpOnly 只能由服务端设置,前端 JavaScript 不能给 document.cookie 设置 HttpOnly。需要保护会话标识时,通常让服务端写 HttpOnly + Secure + 合理 SameSite 的 Cookie。

localStorage 和 sessionStorage 读写简单,但同步 API 会阻塞主线程,也没有复杂查询能力。数据量变大、结构变复杂或需要离线索引时,更适合 IndexedDB。

代码示例

下面示例展示四类存储的典型使用方式和边界。

JavaScript
document.cookie = 'theme=dark; Max-Age=2592000; Path=/; SameSite=Lax; Secure'

localStorage.setItem('sidebar-collapsed', 'true')
const collapsed = localStorage.getItem('sidebar-collapsed') === 'true'

sessionStorage.setItem('checkout-step', 'address')

const request = indexedDB.open('blog-cache', 1)
request.onupgradeneeded = () => {
  const db = request.result
  db.createObjectStore('articles', { keyPath: 'id' })
}

常见误区

  • 把 token 放 localStorage 后忽略 XSS 风险。
  • 用 Cookie 存大量前端状态,增加每次请求体积。
  • 认为 sessionStorage 在所有标签页共享。它通常按标签页隔离。

作者信息