localStorage、sessionStorage 与 Cookie 到底有什么区别
前言
前端开发中经常需要在浏览器保存数据,例如:
用户选择的主题;
当前标签页的临时表单;
用户登录后的会话标识。
常见方案有:
localStorage
sessionStorage
Cookie
它们都能在浏览器中保存字符串数据,但设计目的并不相同:
localStorage、sessionStorage
→ 主要用于浏览器本地存储
Cookie
→ 主要用于浏览器和服务器之间维持状态
对于前端秋招,不需要深入浏览器存储实现,重点是能说清楚:
数据能够保存多久;
数据在什么范围内共享;
是否自动发送给服务器;
容量有什么区别;
登录场景应该注意什么。
一、先看核心对比
| 对比项 | localStorage | sessionStorage | Cookie |
|---|---|---|---|
| 主要用途 | 长期保存前端数据 | 当前标签页的临时数据 | 浏览器与服务器维持状态 |
| 生命周期 | 无自动过期时间,直到主动清除或被浏览器处理 | 当前标签页会话期间,刷新仍保留,关闭标签页后通常清除 | 由 Expires、Max-Age 决定;未设置时通常是会话 Cookie |
| 常见容量 | 约 5MB/源,具体由浏览器决定 | 约 5MB/源,具体由浏览器决定 | 单个通常约 4KB,数量也有限制 |
| 作用范围 | 按同源隔离,同源标签页共享 | 按同源和标签页隔离 | 由 Domain、Path、SameSite 等属性决定 |
| 是否随 HTTP 请求发送 | 否 | 否 | 满足匹配条件时自动发送 |
| JavaScript 能否读取 | 可以 | 可以 | 普通 Cookie 可以,HttpOnly Cookie 不可以 |
| API | localStorage | sessionStorage | document.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 状态管理的机制。选择哪一种,取决于数据需要保存多久、是否需要发给服务器以及安全要求。