最根本差异是cookie自动随HTTP请求发送而localStorage不会。cookie由服务端Set-Cookie控制,支持路径、域名、HttpOnly等安全属性;localStorage由JS手动操作,无自动传输、无细粒度作用域,但容量大、省带宽。

cookie 会自动随 HTTP 请求发送,localStorage 不会
这是最根本的差异。每次浏览器向同域服务器发起请求(包括页面跳转、fetch、XMLHttpRequest),只要 cookie 没过期且路径匹配,就会被自动附加在 Cookie 请求头里。而 localStorage 完全由 JavaScript 控制,不参与网络通信。
这意味着:
- 用
cookie传用户身份标识(如sessionid)是顺手的,但也会带来额外带宽开销(尤其设了多个、较大的 cookie) -
localStorage存 token 更省流量,但你得手动在每次fetch时加Authorization头 - 服务端无法“被动收到”
localStorage数据 —— 想让后端知道,必须显式发过去
cookie 有路径、域名、过期时间等严格作用域控制,localStorage 只看协议+域名+端口
cookie 的 Path、Domain、Secure、HttpOnly 等属性决定了它在哪能读、哪能写、是否暴露给 JS。比如:
document.cookie = "token=abc; Path=/api; Domain=.example.com; Secure; HttpOnly"
这段代码实际无效 —— 因为 HttpOnly cookie 无法通过 document.cookie 设置或读取,只能由服务端 Set-Cookie 响应头下发。
立即学习“前端免费学习笔记(深入)”;
而 localStorage 没有这些细粒度控制:只要协议(https vs http)、域名(example.com)、端口(:3000)三者完全一致,就能互相访问;子域名之间默认隔离(a.example.com 和 b.example.com 不能共享)。
把任意文章或文档内容转换成精美的全屏翻页 HTML 演示文件(幻灯片风格)。当用户发来一篇文章、文档链接、Markdown 内容、或粘贴的文本,并且希望生成演示用的 HTML 时触发。支持任意内容来源:iWiki 链接、KM 链接、本地文件路径、直接粘贴的文本。生成的 HTML 文件保存到本地工作区,并通过企微直接发送给用户。触发词示例:帮我把这篇文章做成PPT、转成演示文档、生成HTML幻灯片、做个演示、转成可以演示的格式、article to deck、make a slide。
- 想让登录态在多个子域间共享?
cookie可设Domain=.example.com;localStorage需靠postMessage+ iframe 中转 - 敏感数据别存
localStorage—— XSS 攻击可直接读取;HttpOnlycookie 至少能防这种偷取 -
cookie最大 4KB,localStorage通常 5–10MB,但不同浏览器差异大
cookie 默认不支持 JSON,localStorage 存对象要自己序列化
cookie 值只能是字符串,且不能含逗号、分号、空格等特殊字符(否则会被截断)。即使你写 document.cookie = "user={name:'a'}",实际存进去的只是 {name:'a'} 这个字面量字符串,服务端收到后还得自己解析。
localStorage 同样只接受字符串值,所以存对象必须手动 JSON.stringify(),取的时候 JSON.parse():
localStorage.setItem('user', JSON.stringify({ id: 123, name: 'Alice' }));
const user = JSON.parse(localStorage.getItem('user') || '{}');
容易踩的坑:
- 没做
try...catch——JSON.parse()遇到损坏数据直接抛错,导致后续 JS 中断 - 存了
undefined或函数 ——JSON.stringify()会忽略它们,取出来是空对象或丢失字段 - 用
localStorage存大量数据时,setItem是同步阻塞操作,可能卡主线程(尤其低端设备)
cookie 可被服务端主动清除,localStorage 必须前端自己删
服务端响应中带上 Set-Cookie: token=; expires=Thu, 01 Jan 1970 00:00:00 GMT,就能强制清掉客户端对应 cookie。但 localStorage 没有这种机制 —— 登出时前端必须显式调用 localStorage.removeItem('token') 或 localStorage.clear()。
更麻烦的是跨标签页场景:
- 用户在标签页 A 登出,删了
localStorage,但标签页 B 还留着旧值,继续发请求会失败 - 可以用
storage事件监听其他标签页的修改:window.addEventListener('storage', e => { if (e.key === 'token') handleLogout() }) - 但这个事件不会在触发修改的当前页触发 —— 所以登出逻辑仍要同时删本地数据 + 发通知
真正难处理的不是怎么存,是怎么让所有活跃上下文及时感知状态变化。cookie 的服务端控制力在这里仍是不可替代的。


















