公众号:小博的前端笔记
1、核心浏览器存储方式:
-
Cookie
-
本质: 小型文本字符串(通常由服务器通过
Set-Cookie
HTTP响应头设置,也可由客户端JavaScript通过document.cookie
读写)。 -
容量: 非常小(通常每个域名下限制为4KB左右,且浏览器对单个域名下的Cookie总数也有限制,通常为20-50个)。
-
生命周期:
- 会话Cookie: 无
Expires
或Max-Age
属性,浏览器关闭即失效。 - 持久Cookie: 有
Expires
(到期日期)或Max-Age
(存活秒数)属性,到期后失效。
- 会话Cookie: 无
-
作用域:
- Domain: 指定哪些主机可以接收该Cookie(默认为设置Cookie时的域名,不包括子域名;可显式设置
.example.com
来包含所有子域名)。 - Path: 指定URL路径前缀,只有匹配该路径的请求才会携带Cookie(默认为设置时的路径)。
- Domain: 指定哪些主机可以接收该Cookie(默认为设置Cookie时的域名,不包括子域名;可显式设置
-
自动携带: 每次HTTP请求(包括页面、图片、API、CSS等)都会自动将匹配作用域的Cookie放在
Cookie
请求头中发送给服务器。 这是Cookie最显著的特点。 -
主要用途:
- 会话管理(Session ID):服务器用于识别用户会话状态的核心机制。
- 用户个性化(主题、语言偏好等)。
- 用户行为追踪(广告、分析)。
-
安全相关属性:
-
Secure
: 仅通过HTTPS连接发送。 -
HttpOnly
: 无法通过JavaScript的document.cookie
访问,防止XSS攻击窃取敏感Cookie(如Session ID)。强烈建议用于会话标识符。 -
SameSite
: 控制Cookie在跨站请求时是否发送。值有:Strict
: 仅在当前站点上下文(URL栏显示的站点)发送。Lax
: (现代浏览器默认)在安全的跨站请求(如导航到目标站点的GET请求)中发送,但如POST
请求或<iframe>
加载则不发送。平衡安全与功能。None
: 允许跨站发送(必须同时设置Secure
)。
-
-
JavaScript访问: 通过
document.cookie
读写,操作相对繁琐(需要手动解析字符串)。 -
面试要点:
- 小容量,自动随请求发送。
- HttpOnly对安全的重要性。
- SameSite的作用(防止CSRF攻击,提升隐私)。
- 与服务器端Session的关系(Cookie通常只存Session ID,用户状态数据在服务器)。
-
-
Web Storage
(Local Storage & Session Storage)-
本质: 浏览器提供的键值对(Key-Value)存储API(
localStorage
和sessionStorage
),操作简单。 -
容量: 远大于Cookie,通常为5-10MB(不同浏览器不同) 。存储的是字符串。
-
作用域: 基于协议、域名和端口(同源策略)。不同源(协议/域名/端口任一不同)完全隔离。
-
生命周期:
localStorage
: 持久化存储。除非用户清除浏览器缓存或代码显式删除,否则数据一直存在,即使关闭浏览器或重启电脑。sessionStorage
: 会话级存储 。数据仅在当前浏览器标签页或窗口 的生命周期内有效。关闭标签页/窗口即清除。刷新页面会保留,但新开标签页(即使是同源页面)或窗口会创建新的独立sessionStorage。
-
API: 非常简洁:
javascript// 存储 localStorage.setItem('key', 'value'); // 或 localStorage.key = 'value'; sessionStorage.setItem('key', 'value'); // 读取 const value = localStorage.getItem('key'); // 或 const value = localStorage.key; // 删除 localStorage.removeItem('key'); // 清空 localStorage.clear(); sessionStorage.clear();
-
数据格式: 键和值都必须是字符串 。存储对象需用
JSON.stringify()
,读取时用JSON.parse()
。 -
不自动发送: 数据不会自动随HTTP请求发送到服务器。
-
主要用途:
localStorage
: 需要持久化的用户偏好设置(如深色模式、布局)、缓存非关键性应用状态、保存离线数据草稿。sessionStorage
: 存储当前标签页会话的临时数据(如表单分步骤填写时的中间状态、单页应用(SPA)的路由状态或组件间临时传递数据)。
-
面试要点:
- 区分
localStorage
(持久) 和sessionStorage
(会话/标签页级)。 - 容量比Cookie大得多。
- 同源策略隔离。
- 纯客户端存储,不自动发送到服务器。
- 只能存字符串,需手动处理对象序列化。
- 区分
-
-
IndexedDB
-
本质: 浏览器内置的非关系型(NoSQL)数据库。功能强大,支持存储大量结构化数据(甚至是文件/Blob)。
-
容量: 理论上是"无上限"的(通常占用户磁盘空间的很大一部分,如50%或更多),但浏览器会管理配额并可能提示用户。 具体限制因浏览器和存储设备而异。
-
数据模型: 基于"对象存储"(Object Stores),类似于数据库表。数据以键值对形式存储,值可以是复杂JavaScript对象(无需序列化成字符串)、数组、文件、Blob等。支持索引进行高效查询。
-
操作方式: 异步API(基于事件或Promise)。操作(打开数据库、创建存储、增删改查)不会阻塞主线程。
-
事务支持: 提供事务机制保证数据操作的原子性和一致性(ACID特性)。
-
查询能力: 支持基于键、索引的范围查询和游标遍历,功能比Web Storage强大得多。
-
作用域: 同源策略。
-
生命周期: 持久化存储。除非用户清除网站数据,否则数据会一直保留。
-
主要用途:
- 存储大量结构化客户端数据(如用户生成的文档、邮件、笔记)。
- 离线Web应用的核心数据存储。
- 缓存大型数据集(如图库、产品目录)以实现快速访问。
- 存储文件或二进制数据(Blob)。
-
面试要点:
- 强大的客户端数据库,支持大量结构化数据和二进制数据。
- 异步API,不阻塞主线程。
- 支持事务和索引。
- 持久化存储,容量大。
- 适用于需要复杂查询或离线功能的场景。是替代已废弃的Web SQL Database的标准方案。
-
其他相关存储机制(了解即可):
-
Cache API
(Service Worker Cache)- 本质: 属于Service Worker API的一部分,主要用于缓存网络请求(Request)及其响应(Response)。
- 用途: 实现离线应用(Progressive Web App, PWA) 、资源预加载、提升加载速度(从缓存读取而非网络)。
- 存储内容: HTTP请求/响应对(包括HTML, CSS, JS, 图片,API响应等)。
- 控制权: 由Service Worker脚本完全控制缓存策略(何时存、存什么、何时用、何时更新)。
- 生命周期: 持久化存储,但可由Service Worker或用户清除缓存。
- 容量: 浏览器管理配额(通常与其他存储如IndexedDB共享一个较大配额)。
- 面试要点: PWA离线能力的核心,缓存网络资源。区别于存储应用数据的IndexedDB/Web Storage。
-
Web SQL Database
(已废弃 - Deprecated)- 本质: 曾试图提供一个基于SQL的客户端数据库(类似SQLite)。
- 状态: W3C已废弃该规范。不再建议用于新项目。
- 替代方案:
IndexedDB
是官方推荐的标准替代方案。 - 面试要点: 知道它存在过但已被废弃,IndexedDB是现在的主流选择。
总结对比表:
特性 | Cookie | localStorage | sessionStorage | IndexedDB | Cache API |
---|---|---|---|---|---|
容量 | ~4KB (很小) | ~5-10MB (较大) | ~5-10MB (较大) | 非常大 (GB级, 有配额) | 较大 (有配额) |
生命周期 | 会话或设置过期时间 | 永久 (直到清除) | 当前标签页/窗口 (关闭即清除) | 永久 (直到清除) | 永久 (直到清除或失效策略触发) |
作用域 | Domain/Path | 同源 | 同源 + 当前标签页/窗口 | 同源 | 同源 (可跨Service Worker作用域) |
数据格式 | 文本字符串 | 字符串 (需序列化对象) | 字符串 (需序列化对象) | 结构化数据、对象、文件/Blob | Request/Response 对象 |
访问方式 | 文档 document.cookie / 自动HTTP头 |
同步 API | 同步 API | 异步 API (事件/Promise) | 异步 API (Promise) |
自动发送到服务器 | 是 (每次HTTP请求) | 否 | 否 | 否 | 否 |
主要用途 | 会话管理、小量用户设置、追踪 | 持久化用户设置、离线数据缓存 | 当前会话/标签页临时数据 | 大量结构化数据、离线应用核心数据、文件缓存 | 网络资源缓存 (PWA离线、加速) |
关键特性 | HttpOnly , Secure , SameSite 安全属性 |
简单键值存储 | 标签页/窗口隔离 | 事务、索引、查询、大容量、二进制支持 | Service Worker 控制缓存策略 |
面试强调点 | 小、自动带、安全属性、Session ID载体 | 持久、同源、字符串、容量适中 | 会话级、标签页隔离、临时数据 | 强大DB、异步、事务、大存储、离线核心 | PWA离线能力核心、缓存网络资源 |
回答建议:
- 结构化清晰: 按顺序介绍Cookie、Web Storage (区分local/session)、IndexedDB、再提一下Cache API和废弃的Web SQL。
- 突出关键区别: 重点对比容量、生命周期、作用域、是否自动发送、主要用途。
- 结合实际场景: 举例说明每种存储最适合什么情况(如Session ID用Cookie,用户设置用localStorage,购物车复杂数据用IndexedDB)。
- 强调安全性: 提到Cookie的
HttpOnly
、Secure
、SameSite
属性对于安全的重要性。 - 提及现代趋势: 说明IndexedDB是复杂客户端存储和PWA的基石,Cache API是实现离线应用的关键。
- 简洁准确: 使用上表中的关键词(如同源、持久化、会话级、异步、事务、配额等)。
2、cookie的Domain如何使用:
一、Domain 属性的核心作用
- 作用域控制 指定哪些主机(域名)可以接收该 Cookie。
- 子域名共享 显式设置 Domain 可实现跨子域名共享 Cookie(如
a.example.com
和b.example.com
)。
二、Domain 设置规则
▶️ 规则 1:默认作用域
-
不设置 Domain 时 : Cookie 默认绑定到当前文档的域名(不包括子域名)。
ini# 当前 URL:www.example.com Set-Cookie: name=value; # 仅 www.example.com 可用,子域名(如 api.example.com)不可用
▶️ 规则 2:显式设置作用域
-
设置
Domain=.example.com
(注意开头的点): 该 Cookie 对当前域名及其所有子域名生效。ini# 服务端设置(响应头) Set-Cookie: sessionId=abc123; Domain=.example.com; # 结果: # ✅ 生效域名: example.com # ✅ 生效子域名: www.example.com, api.example.com, shop.example.com
▶️ 规则 3:禁止跨顶级域名
-
不可设置为非当前域名的上级域名:
ini# 当前域名: www.example.com Set-Cookie: name=value; Domain=.google.com; ❌ 浏览器会拒绝此设置!
三、关键注意事项
-
开头的点(
.
)可选但建议省略 现代浏览器会自动处理Domain=example.com
和Domain=.example.com
,二者效果相同(均包含子域名)。iniSet-Cookie: name=value; Domain=example.com; // ✅ 等同于 .example.com
-
子域名间的 Cookie 隔离
ini# 在 shop.example.com 设置: Set-Cookie: cart_id=123; Domain=shop.example.com; # ❌ 其他子域名(如 blog.example.com)无法访问此 Cookie
-
Path 属性的联动影响 Cookie 访问需同时满足 Domain 和 Path 匹配:
iniSet-Cookie: user=Alice; Domain=.example.com; Path=/shop;
- ✅ 可访问的 URL:
https://shop.example.com/shop/checkout
- ❌ 不可访问:
https://shop.example.com/home
(Path 不匹配)
- ✅ 可访问的 URL:
四、JavaScript 设置 Domain
ini
// 正确设置(允许子域名访问)
document.cookie = "theme=dark; Domain=.example.com; Path=/; Secure";
// 错误示例(尝试跨顶级域名)
document.cookie = "token=xyz; Domain=.google.com; ❌ 设置失败!";
五、常见问题场景
问题 1:如何让主站和子站共享登录状态?
ini
# 在 login.example.com 登录后设置:
Set-Cookie: session_id=xxxx; Domain=.example.com; Path=/; HttpOnly
- 所有
*.example.com
均可读取此 Cookie,实现单点登录(SSO)。
问题 2:为什么本地测试时 Cookie 不共享?
- 本地开发环境 (如
localhost
、127.0.0.1
): 无法设置Domain=localhost
(非标准域名),需通过 同 IP/端口 访问。
六、Domain 安全规范
-
不要随意扩大作用域 仅将 Cookie 暴露给必要域名,减少攻击面。
-
配合
SameSite
和Secure
跨子域共享时,务必添加安全属性:iniSet-Cookie: session=xxxx; Domain=.example.com; Path=/; SameSite=Lax; Secure; HttpOnly