浏览器各个存储方式及其对比

公众号:小博的前端笔记

1、核心浏览器存储方式:

  1. Cookie

    • 本质: 小型文本字符串(通常由服务器通过Set-Cookie HTTP响应头设置,也可由客户端JavaScript通过document.cookie读写)。

    • 容量: 非常小(通常每个域名下限制为4KB左右,且浏览器对单个域名下的Cookie总数也有限制,通常为20-50个)。

    • 生命周期:

      • 会话Cookie:ExpiresMax-Age属性,浏览器关闭即失效。
      • 持久Cookie:Expires(到期日期)或Max-Age(存活秒数)属性,到期后失效。
    • 作用域:

      • Domain: 指定哪些主机可以接收该Cookie(默认为设置Cookie时的域名,不包括子域名;可显式设置.example.com来包含所有子域名)。
      • Path: 指定URL路径前缀,只有匹配该路径的请求才会携带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,用户状态数据在服务器)。
  2. Web Storage (Local Storage & Session Storage)

    • 本质: 浏览器提供的键值对(Key-Value)存储API(localStoragesessionStorage),操作简单。

    • 容量: 远大于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大得多。
      • 同源策略隔离。
      • 纯客户端存储,不自动发送到服务器。
      • 只能存字符串,需手动处理对象序列化。
  3. IndexedDB

    • 本质: 浏览器内置的非关系型(NoSQL)数据库。功能强大,支持存储大量结构化数据(甚至是文件/Blob)。

    • 容量: 理论上是"无上限"的(通常占用户磁盘空间的很大一部分,如50%或更多),但浏览器会管理配额并可能提示用户。 具体限制因浏览器和存储设备而异。

    • 数据模型: 基于"对象存储"(Object Stores),类似于数据库表。数据以键值对形式存储,值可以是复杂JavaScript对象(无需序列化成字符串)、数组、文件、Blob等。支持索引进行高效查询。

    • 操作方式: 异步API(基于事件或Promise)。操作(打开数据库、创建存储、增删改查)不会阻塞主线程。

    • 事务支持: 提供事务机制保证数据操作的原子性和一致性(ACID特性)。

    • 查询能力: 支持基于键、索引的范围查询和游标遍历,功能比Web Storage强大得多。

    • 作用域: 同源策略。

    • 生命周期: 持久化存储。除非用户清除网站数据,否则数据会一直保留。

    • 主要用途:

      • 存储大量结构化客户端数据(如用户生成的文档、邮件、笔记)。
      • 离线Web应用的核心数据存储。
      • 缓存大型数据集(如图库、产品目录)以实现快速访问。
      • 存储文件或二进制数据(Blob)。
    • 面试要点:

      • 强大的客户端数据库,支持大量结构化数据和二进制数据。
      • 异步API,不阻塞主线程。
      • 支持事务和索引。
      • 持久化存储,容量大。
      • 适用于需要复杂查询或离线功能的场景。是替代已废弃的Web SQL Database的标准方案。

其他相关存储机制(了解即可):

  1. 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。
  2. 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离线能力核心、缓存网络资源

回答建议:

  1. 结构化清晰: 按顺序介绍Cookie、Web Storage (区分local/session)、IndexedDB、再提一下Cache API和废弃的Web SQL。
  2. 突出关键区别: 重点对比容量、生命周期、作用域、是否自动发送、主要用途。
  3. 结合实际场景: 举例说明每种存储最适合什么情况(如Session ID用Cookie,用户设置用localStorage,购物车复杂数据用IndexedDB)。
  4. 强调安全性: 提到Cookie的HttpOnlySecureSameSite属性对于安全的重要性。
  5. 提及现代趋势: 说明IndexedDB是复杂客户端存储和PWA的基石,Cache API是实现离线应用的关键。
  6. 简洁准确: 使用上表中的关键词(如同源、持久化、会话级、异步、事务、配额等)。

2、cookie的Domain如何使用:

一、Domain 属性的核心作用

  1. 作用域控制 指定哪些主机(域名)可以接收该 Cookie。
  2. 子域名共享 显式设置 Domain 可实现跨子域名共享 Cookie(如 a.example.comb.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; ❌ 浏览器会拒绝此设置!

三、关键注意事项

  1. 开头的点(.)可选但建议省略 现代浏览器会自动处理 Domain=example.comDomain=.example.com,二者效果相同(均包含子域名)。

    ini 复制代码
    Set-Cookie: name=value; Domain=example.com;  // ✅ 等同于 .example.com
  2. 子域名间的 Cookie 隔离

    ini 复制代码
    # 在 shop.example.com 设置:
    Set-Cookie: cart_id=123; Domain=shop.example.com;
    ​
    # ❌ 其他子域名(如 blog.example.com)无法访问此 Cookie
  3. Path 属性的联动影响 Cookie 访问需同时满足 Domain Path 匹配:

    ini 复制代码
    Set-Cookie: user=Alice; Domain=.example.com; Path=/shop;
    • ✅ 可访问的 URL: https://shop.example.com/shop/checkout
    • ❌ 不可访问: https://shop.example.com/home(Path 不匹配)

四、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)。
  • 本地开发环境 (如 localhost127.0.0.1): 无法设置 Domain=localhost(非标准域名),需通过 同 IP/端口 访问。

六、Domain 安全规范

  1. 不要随意扩大作用域 仅将 Cookie 暴露给必要域名,减少攻击面。

  2. 配合 SameSiteSecure 跨子域共享时,务必添加安全属性:

    ini 复制代码
    Set-Cookie: session=xxxx; Domain=.example.com; Path=/; SameSite=Lax; Secure; HttpOnly

附:Domain 设置流程图

相关推荐
ze_juejin几秒前
async、defer 和 module 属性的比较
前端
归于尽2 分钟前
关于数组的这些底层你真的知道吗?
前端·javascript
puppy0_04 分钟前
前端性能优化基石:HTML解析与资源加载机制详解
前端·性能优化
三小河4 分钟前
e.target 和 e.currentTarget 的区别
前端
一只卡比兽5 分钟前
无界微前端框架深度配置指南:20+ 关键配置项详解
前端
一只卡比兽5 分钟前
深入解析前端微服务框架无界:实现、通信与实战示例
前端
WildBlue15 分钟前
小白也能懂!react-router-dom 超详细指南🚀
前端·react.js
unicrom_深圳市由你创科技24 分钟前
使用Django框架构建Python Web应用
前端·python·django
火车叼位26 分钟前
Node vs Element:DOM 节点类型区分
前端
颜酱1 小时前
使用useReducer和Context进行React中的页面内部数据共享
前端·javascript·react.js