localStorage、sessionStorage 与 Cookie 到底有什么区别

3 阅读13分钟

localStorage、sessionStorage 与 Cookie 到底有什么区别

前言

前端开发中经常需要在浏览器保存数据,例如:

用户选择的主题;
当前标签页的临时表单;
用户登录后的会话标识。

常见方案有:

localStorage
sessionStorage
Cookie

它们都能在浏览器中保存字符串数据,但设计目的并不相同:

localStorage、sessionStorage
    → 主要用于浏览器本地存储

Cookie
    → 主要用于浏览器和服务器之间维持状态

对于前端秋招,不需要深入浏览器存储实现,重点是能说清楚:

数据能够保存多久;
数据在什么范围内共享;
是否自动发送给服务器;
容量有什么区别;
登录场景应该注意什么。

一、先看核心对比

对比项localStoragesessionStorageCookie
主要用途长期保存前端数据当前标签页的临时数据浏览器与服务器维持状态
生命周期无自动过期时间,直到主动清除或被浏览器处理当前标签页会话期间,刷新仍保留,关闭标签页后通常清除ExpiresMax-Age 决定;未设置时通常是会话 Cookie
常见容量约 5MB/源,具体由浏览器决定约 5MB/源,具体由浏览器决定单个通常约 4KB,数量也有限制
作用范围按同源隔离,同源标签页共享按同源和标签页隔离由 Domain、Path、SameSite 等属性决定
是否随 HTTP 请求发送满足匹配条件时自动发送
JavaScript 能否读取可以可以普通 Cookie 可以,HttpOnly Cookie 不可以
APIlocalStoragesessionStoragedocument.cookie 或服务端响应头
数据类型字符串字符串字符串

最简记忆:

localStorage:关闭浏览器后通常还在
sessionStorage:当前标签页关闭后通常清除
Cookie:符合条件时会随 HTTP 请求自动发送

二、localStorage 是什么

localStorage 用于在当前源下长期保存少量前端数据。

localStorage.setItem('theme', 'dark')

关闭标签页甚至重启浏览器后,再次访问同源页面,通常仍然可以读取:

const theme = localStorage.getItem('theme')

console.log(theme)
// 'dark'

1. 常用 API

// 保存
localStorage.setItem('theme', 'dark')

// 读取
localStorage.getItem('theme')

// 删除一个字段
localStorage.removeItem('theme')

// 清空当前源的 localStorage
localStorage.clear()

// 当前保存了多少个字段
localStorage.length

// 根据下标获取字段名
localStorage.key(0)

读取不存在的字段时返回:

null

2. 只能直接保存字符串

下面保存的是字符串:

localStorage.setItem('count', '10')

读取结果也是字符串:

const count = localStorage.getItem('count')

console.log(typeof count)
// 'string'

保存对象时需要序列化:

const user = {
  id: 1001,
  name: '小明'
}

localStorage.setItem(
  'user',
  JSON.stringify(user)
)

读取后反序列化:

const userText = localStorage.getItem('user')

const user = userText
  ? JSON.parse(userText)
  : null

3. 适合保存什么

主题偏好;
语言选择;
用户主动保存的草稿;
刷新后仍希望保留的非敏感设置。

4. “永久保存”并不准确

localStorage 没有开发者设置的自动过期时间,但不代表永远不会消失。

它仍可能因为下面这些情况被清除:

用户清理网站数据;
浏览器隐私模式结束;
浏览器存储策略和空间管理;
代码主动执行 removeItem 或 clear。

所以面试中更准确的说法是:

localStorage 默认没有过期时间,会持续保存,直到用户、浏览器或代码将它清除。


三、sessionStorage 是什么

sessionStorage 用于保存当前标签页会话中的临时数据。

sessionStorage.setItem(
  'formStep',
  '2'
)

它与 localStorage 使用相同的 Storage API:

sessionStorage.setItem('key', 'value')
sessionStorage.getItem('key')
sessionStorage.removeItem('key')
sessionStorage.clear()

1. 刷新后还在吗

还在。

当前标签页刷新
    ↓
sessionStorage 通常仍然保留

它不是“一刷新就消失”。

2. 什么时候消失

通常在当前标签页关闭后,对应页面会话结束,数据被清除:

刷新页面     → 保留
同标签页跳转 → 同源情况下可以继续使用
关闭标签页   → 通常清除

3. 不同标签页是否共享

sessionStorage 不仅按源隔离,还按顶层浏览上下文,也就是标签页隔离。

可以简单理解为:

标签页 A 的 sessionStorage
        ≠
标签页 B 的 sessionStorage

即使两个标签页打开的是同一个网站,它们通常也维护各自的 sessionStorage。

面试中回答“同源标签页之间共享 sessionStorage”通常是错误的。

4. 适合保存什么

当前标签页的多步骤表单进度;
一次会话内的临时筛选条件;
刷新后需要恢复、关闭标签页后不需要的数据。

四、localStorage 与 sessionStorage 的共同点

它们都属于 Web Storage API,具有以下共同特点:

按源隔离;
通过 JavaScript 主动读写;
不会自动随 HTTP 请求发送;
key 和 value 都按字符串处理;
API 是同步的。

什么叫同源

协议、域名和端口都相同,才属于同源:

https://example.com:443
│       │           │
协议    域名         端口

例如:

https://example.com/a
https://example.com/b

属于同源。

但下面两个地址不同源:

https://example.com
http://example.com

因为协议不同。

下面也不同源:

https://example.com
https://api.example.com

因为主机名不同。

同步 API 有什么影响

localStorage.getItem('user')
localStorage.setItem('user', text)

会在当前 JavaScript 调用中同步完成。

少量简单数据通常没有问题,但不要高频读写大量内容,否则可能阻塞主线程。大量结构化数据更适合评估 IndexedDB,不过这不属于本文的秋招重点。


五、Cookie 是什么

HTTP 本身是无状态的:

第一次请求 /login
第二次请求 /profile

服务器默认不会只凭这两次请求就知道它们来自同一个登录用户。

Cookie 可以帮助浏览器和服务器携带状态标识。

登录成功后,服务器可能返回:

Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure; SameSite=Lax

浏览器保存 Cookie。之后请求匹配的网站路径时,浏览器可能自动发送:

GET /profile HTTP/1.1
Host: example.com
Cookie: sessionId=abc123

服务器读取 sessionId,再查找对应登录会话。

这就是 Cookie 与 Web Storage 最核心的不同:

localStorage / sessionStorage
    → 不会自动进入 HTTP 请求

Cookie
    → 满足作用范围和安全条件时自动随请求发送

六、Cookie 怎样设置和读取

1. 服务端设置

服务器通过响应头设置:

Set-Cookie: theme=dark; Max-Age=86400; Path=/; SameSite=Lax

对于登录会话,常见形式是:

Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure; SameSite=Lax

2. JavaScript 设置

document.cookie = 'theme=dark; Max-Age=86400; Path=/'

3. JavaScript 读取

console.log(document.cookie)

可能得到:

theme=dark; language=zh-CN

document.cookie 返回的是一整段字符串,原生操作没有 Web Storage API 那么直观。

如果 Cookie 设置了 HttpOnly

Set-Cookie: sessionId=abc123; HttpOnly

JavaScript 无法通过 document.cookie 读取它,但浏览器仍可以在符合条件的请求中自动携带。


七、Cookie 常见属性

Expires 和 Max-Age

控制 Cookie 生命周期。

Set-Cookie: theme=dark; Max-Age=86400

Max-Age=86400 表示相对当前时间保存 86400 秒。

Set-Cookie: theme=dark; Expires=Wed, 21 Oct 2026 07:28:00 GMT

Expires 使用具体到期时间。

如果都没有设置,通常是会话 Cookie,由浏览器会话管理;实际行为还可能受到浏览器会话恢复功能影响。

Domain

控制 Cookie 可以发送到哪些域名。

不设置 Domain 时,Cookie 默认只匹配设置它的主机。

Domain=example.com

可以扩大到符合规则的子域名范围,但不能随意设置到完全无关的网站。

Path

控制请求路径范围:

Path=/admin

通常会匹配:

/admin
/admin/users

不会匹配普通的:

/products

Path 主要用于控制 Cookie 发送范围,不应该被当作真正的安全隔离机制。

Secure

Secure

表示 Cookie 只通过 HTTPS 等安全连接发送。

HttpOnly

HttpOnly

表示 JavaScript 不能通过 document.cookie 读取 Cookie。

它常用于保存会话标识,降低会话标识被 XSS 脚本直接读取并带走的风险。

SameSite

控制 Cookie 在跨站请求中的发送行为:

Strict
Lax
None

它可以降低部分 CSRF 风险。使用:

SameSite=None

时还需要配合:

Secure

需要注意,SameSite 是 CSRF 防护的一部分,不代表设置以后就不需要其他安全措施。


八、Cookie 与 localStorage 保存登录信息的区别

这是秋招非常常见的问题。

localStorage 保存 token

localStorage.setItem('token', token)

请求时由前端主动读取并添加:

const token = localStorage.getItem('token')

fetch('/api/user', {
  headers: {
    Authorization: `Bearer ${token}`
  }
})

特点:

不会自动随请求发送;
前端需要手动添加请求头;
页面 JavaScript 可以读取;
发生 XSS 时 token 可能被恶意脚本读取。

HttpOnly Cookie 保存会话标识

服务器设置:

Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax; Path=/

特点:

符合条件时浏览器自动发送;
前端 JavaScript 无法直接读取 HttpOnly Cookie;
能够降低会话标识被脚本直接窃取的风险;
仍然需要考虑 CSRF 和 XSS 防护。

不要得出绝对结论

不能简单回答:

Cookie 一定不安全;
localStorage 一定安全;
只要 HttpOnly 就没有 XSS;
只要 SameSite 就没有 CSRF。

更合理的秋招回答是:

localStorage 中的数据可以被同源 JavaScript 读取,通常由前端手动加入请求;Cookie 可以通过 HttpOnly 限制 JavaScript 读取,并在满足条件时自动发送,但需要结合 Secure、SameSite 和服务端 CSRF 防护。具体方案应该由前后端根据登录架构统一设计。


九、三者分别适合什么场景

localStorage

主题设置;
语言偏好;
需要跨标签页、跨浏览器重启保留的非敏感配置;
用户主动保存的本地草稿。

sessionStorage

当前标签页的临时表单;
一次页面流程中的中间状态;
刷新后保留、关闭标签页后不再需要的数据。

Cookie

服务端会话标识;
需要自动随匹配请求发送的少量状态;
由服务器参与控制生命周期和安全属性的数据。

不建议使用 Cookie 保存大量纯前端数据,因为:

单个容量小;
数量有限;
匹配时会增加 HTTP 请求大小;
原生读写 API 不够方便。

十、它们和 Vuex、Pinia 有什么关系

Vuex、Pinia 与浏览器存储不是同一种东西:

Vuex / Pinia
    → 运行时响应式状态管理

localStorage / sessionStorage / Cookie
    → 浏览器存储和 HTTP 状态机制

例如 Pinia 中:

userStore.user = user

可以让组件响应更新,但刷新页面后内存状态会重新初始化。

如果需要恢复主题,可以组合使用:

localStorage 保存主题
        ↓
应用启动时读取
        ↓
写入 Pinia state
        ↓
组件响应更新

所以:

状态管理负责应用运行期间的数据组织和响应更新,浏览器存储负责在需要时跨刷新保存数据。


十一、常见误区

1. sessionStorage 刷新就消失

错误。刷新当前标签页通常不会清除,关闭对应标签页后才通常结束这次页面会话。

2. localStorage 永久存在

错误。它没有自动过期时间,但仍然可能被用户、浏览器或代码清除。

3. localStorage 可以直接保存对象

错误。它按字符串存储,普通对象通常需要 JSON.stringify()JSON.parse()

4. Cookie 每个请求都会无条件携带

错误。只有请求的域名、路径、Secure、SameSite 等条件匹配时才会携带相应 Cookie。

5. HttpOnly Cookie 前端完全看不到,所以不能登录

错误。前端虽然不能读取 Cookie 值,但浏览器可以自动携带,服务器根据它判断会话,再通过用户接口返回登录信息。

6. 三者都可以跨域读取

错误。Web Storage 按源隔离;Cookie 使用自己的 Domain、Path 和站点规则,也不能随意跨到无关网站。

7. Cookie 只能由服务器设置

错误。普通 Cookie 可以通过 document.cookie 设置,但带有 HttpOnly 的 Cookie 只能通过服务端响应头设置,不能由 JavaScript 创建为 HttpOnly。


十二、秋招高频面试题

1. localStorage、sessionStorage 和 Cookie 有什么区别

可以这样回答:

localStorage 和 sessionStorage 都属于 Web Storage,只在浏览器中由 JavaScript 主动读写,不会自动随请求发送。localStorage 默认没有过期时间,同源页面可以共享;sessionStorage 按同源和标签页隔离,刷新保留,关闭标签页后通常清除。Cookie 容量更小,但满足 Domain、Path、SameSite 等条件时会自动随 HTTP 请求发送,并支持 HttpOnly、Secure 等安全属性。

2. localStorage 和 sessionStorage 能保存对象吗

可以这样回答:

Web Storage 的 key 和 value 按字符串处理。保存普通对象时通常使用 JSON.stringify 序列化,读取后再使用 JSON.parse 还原,并处理字段不存在或 JSON 损坏的情况。

3. sessionStorage 刷新后还存在吗

可以这样回答:

存在。sessionStorage 的生命周期是当前标签页的页面会话,刷新通常不会清除;关闭标签页后数据通常被清除,不同标签页一般拥有独立的 sessionStorage。

4. localStorage 是否会自动发送给服务器

可以这样回答:

不会。localStorage 只能由前端 JavaScript 主动读取。如果其中保存了 token,需要前端代码自行把它加入 Authorization 等请求头。

5. Cookie 为什么不适合保存大量数据

可以这样回答:

Cookie 单个容量通常只有约 4KB,并且满足匹配条件时会附加到 HTTP 请求中。保存大量数据会增加请求大小,所以大量纯前端数据更适合 Web Storage 或 IndexedDB。

6. HttpOnly 有什么作用

可以这样回答:

HttpOnly 会禁止页面 JavaScript 通过 document.cookie 读取 Cookie,常用于保护会话标识,降低 XSS 脚本直接窃取凭证的风险。但它不能消除全部 XSS 风险,也不能单独完成 CSRF 防护。

7. Secure 和 SameSite 有什么作用

可以这样回答:

Secure 限制 Cookie 只通过 HTTPS 等安全连接发送;SameSite 控制 Cookie 在跨站请求中的发送行为,可以降低部分 CSRF 风险。SameSite=None 需要同时设置 Secure。

8. 登录 token 应该放 localStorage 还是 Cookie

可以这样回答:

不能脱离系统架构给出绝对答案。localStorage 需要前端手动添加 token,但同源 JavaScript 可以读取,存在 XSS 窃取风险;HttpOnly Cookie 可以避免 JavaScript 直接读取并由浏览器自动发送,但需要正确配置 Secure、SameSite 并考虑 CSRF。通常应由前后端根据认证方案统一设计。

9. localStorage 在不同标签页之间共享吗

可以这样回答:

同源页面通常共享同一个 localStorage,因此不同同源标签页可以读取相同数据。一个标签页修改 localStorage 时,其他相关同源页面还可以通过 storage 事件感知变化。

10. Cookie 和 Web Storage 的本质区别是什么

可以这样回答:

Web Storage 主要解决浏览器本地键值存储,由 JavaScript 主动读写;Cookie 属于 HTTP 状态机制,浏览器会根据 Cookie 属性决定是否在请求中自动携带。两者的作用范围、生命周期、容量和安全控制方式都不同。


十三、总结

三种方案最核心的区别是:

localStorage
    → 长期保存同源前端数据
    → 不自动发送给服务器

sessionStorage
    → 保存当前标签页会话数据
    → 刷新保留,关闭标签页后通常清除
    → 不自动发送给服务器

Cookie
    → 保存浏览器与服务器之间的少量状态
    → 满足条件时自动随 HTTP 请求发送
    → 支持 HttpOnly、Secure、SameSite 等属性

最后记住:

localStorage 和 sessionStorage 是浏览器本地存储;Cookie 是浏览器参与 HTTP 状态管理的机制。选择哪一种,取决于数据需要保存多久、是否需要发给服务器以及安全要求。


参考资料