【基础键值存储】:Local storage 和 Session storage
虽然在日常口语中我们常把浏览器中 Application - Storage 模块中的多种类型统称为“浏览器缓存”但在计算机科学与 Web 开发的专业定义中实际上包含了“存储”与“缓存”两个截然不同但又紧密相关的概念体系。其中本文将着重介绍的Local storage 和 Session storage 就属于应用数据存储体系。这部分机制的主要目的是持久化保存数据如用户设置、登录状态、业务记录以便在页面刷新或重启后恢复应用状态。它们通常由 JavaScript 代码主动读写。LocalStorage 用于长期保存如主题偏好SessionStorage 仅在当前标签页会话有效如表单草稿。它们不是用来加速网页加载的而是为了记住用户的数据。下边是详细介绍供参考。回到顶部一、什么是 LocalStorage1.1 简介LocalStorage 是浏览器提供的持久化本地存储方案属于 Web Storage API 的一部分并非传统意义上的 HTTP 缓存如强缓存、协商缓存。它主要用于在客户端长期保存非敏感数据数据在浏览器关闭后仍保留且不会随 HTTP 请求自动发送至服务器。其核心价值在于减少服务器请求、提升用户体验适用于用户偏好设置、草稿保存等场景但需注意容量限制和数据类型约束。LocalStorage 是轻量级持久化存储的首选方案适用于 5–10 MB 以内、非敏感的字符串数据典型场景包括用户偏好、表单草稿和小型缓存。其核心优势在于免 HTTP 传输开销和跨会话持久性但需严格规避敏感信息存储并通过容量监控、数据序列化和精准清理策略规避常见陷阱。对于超大容量或结构化数据需求应转向 IndexedDB 等更专业的方案。1.2 核心特征1生命周期与持久性永久存储数据除非被手动清除调用 clear() 或 removeItem()或用户主动清理浏览器缓存否则长期保留即使关闭浏览器、重启设备也不会丢失。同源策略限制仅限协议、域名、端口完全一致的页面访问例如 https://example.com 无法读取 http://example.com 的数据。2存储容量与限制实际容量因浏览器而异Chrome/Edge 桌面版约 10 MBFirefox约 5–10 MBSafariiOS可能低至 1 MB内存紧张时更低微信 WebViewX5 内核常不足 1 MB注意早期“5MB 固定容量”的说法已过时实际空间受设备平台、隐私设置影响。超限处理调用 setItem() 时若超出容量会抛出 QuotaExceededError 异常不会静默失败或截断数据需通过 try-catch 捕获并触发清理逻辑。3数据类型与操作规范仅支持字符串存储直接存入对象/数组会转为 [object Object]必须通过 JSON.stringify() 序列化后存储读取时用 JSON.parse() 还原。基础操作方法setItem(key, value)存储或覆盖数据。getItem(key)读取数据键不存在时返回 null。removeItem(key)删除指定键。clear()清空所有数据。key(index) length遍历存储项避免用 for...in 避免原型链污染。1.3 典型应用场景1用户偏好与配置保存主题色、语言、字体大小等设置避免每次加载时重复请求服务器。// 保存并应用主题localStorage.setItem(theme, dark);document.body.className localStorage.getItem(theme);2表单草稿自动保存实时存储输入内容防止意外关闭页面导致数据丢失textarea.addEventListener(input, () {localStorage.setItem(draft, textarea.value);});// 页面加载时恢复window.addEventListener(DOMContentLoaded, () {textarea.value localStorage.getItem(draft) || ;});注意需通过 JSON.parse()/JSON.stringify() 处理复杂对象。3离线数据缓存存储静态资源如配置文件、API 响应快照在网络中断时提供基础功能支持。但单条数据超过 100 KB 或总量逼近 5 MB 时应改用其他缓存类型如IndexedDB。1.4 常见的踩坑点1避免存储敏感信息LocalStorage 无 HttpOnly 保护若页面存在 XSS 漏洞攻击者可直接读取数据如token。敏感信息如身份凭证应优先通过 HttpOnly Cookie 存储或结合 Web Crypto API 加密后再存。2容量超限的预防策略写入前试探空间先尝试存入测试数据成功后立即删除。预留 10% 余量按 UTF-8 字节计算真实占用new TextEncoder().encode(str).length而非字符串长度。精准清理机制按前缀删除非核心数据如cache_、优先清理过期项避免直接调用 clear()。3特殊环境限制隐身模式部分浏览器如Chrome会完全禁用 localStorage调用时抛出 SecurityError。移动端 WebView容量可能显著低于桌面端如微信 X5 内核常 1 MB需降级处理。回到顶部二、什么是 SessionStorage2.1 简介SessionStorage 是浏览器提供的会话级本地存储方案同样属于 Web Storage API 的一部分也不同于传统 HTTP 缓存机制如强缓存、协商缓存。其核心特点是数据仅在当前浏览器标签页的会话周期内有效标签页关闭后自动清除且不同标签页的 sessionStorage 相互隔离。它适用于临时数据存储不会随 HTTP 请求发送至服务器与服务端的 Session 机制无关。SessionStorage 是专为单次浏览器会话设计的临时存储方案核心价值在于标签页内数据的防丢失与状态延续典型场景包括表单草稿、滚动位置恢复等。其关键优势是自动清理机制关闭标签页即释放资源避免数据残留风险。但需注意不同标签页数据隔离、隐身模式可能失效且绝不适用于跨会话或跨标签页的数据共享。若需跨标签页通信应改用 localStorage storage 事件方案。2.2 核心特性1生命周期与作用域会话级时效性数据仅在当前标签页打开期间有效即使刷新页面或跳转同源页面仍保留但关闭标签页后立即销毁。严格标签页隔离即使同一域名不同标签页的 sessionStorage 完全独立无法跨标签页共享数据例如从 example.com 打开新标签页时新标签页的 sessionStorage 为空。同源策略限制仅限协议、域名、端口完全一致的页面访问例如https://a.example.com 无法读取 https://b.example.com 的数据。2存储容量与操作规范容量限制与 localStorage 类似通常为 5–10 MB实际因浏览器而异超限时抛出 QuotaExceededError 异常。仅支持字符串存储存储对象/数组需通过 JSON.stringify() 序列化读取时用 JSON.parse() 还原。基础操作方法setItem(key, value)存储或覆盖数据。getItem(key)读取数据键不存在时返回 null。removeItem(key)删除指定键。clear()清空当前标签页的所有数据。3事件监听机制storage 事件的特殊性当其他标签页修改同源 localStorage 或 sessionStorage 时会触发当前页面的 storage 事件但当前页面自身修改 sessionStorage 不会触发该事件。window.addEventListener(storage, (e) {console.log(键 ${e.key} 从 ${e.oldValue} 更新为 ${e.newValue});});此特性可用于跨标签页通信需结合 localStorage但 sessionStorage 本身无法直接跨标签页共享数据。2.3 典型应用场景1单次会话的临时数据保护表单草稿防丢失用户填写多步骤表单时将已填内容存入 sessionStorage即使刷新页面也能恢复进度。// 保存输入内容form.addEventListener(input, () {sessionStorage.setItem(formDraft, JSON.stringify(formData));});// 页面加载时恢复window.addEventListener(DOMContentLoaded, () {const draft sessionStorage.getItem(formDraft);if (draft) restoreForm(JSON.parse(draft));});2页面状态临时缓存滚动位置恢复从列表页跳转详情页后返回时自动恢复原滚动位置。// 列表页记录退出时的滚动位置window.addEventListener(beforeunload, () {sessionStorage.setItem(scrollPos, window.scrollY);});// 重新进入列表页恢复位置window.addEventListener(DOMContentLoaded, () {const pos sessionStorage.getItem(scrollPos);if (pos) window.scrollTo(0, parseInt(pos));});3单次会话的防重复操作防止表单重复提交提交后存储标记避免用户快速多次点击导致重复请求。submitButton.addEventListener(click, () {if (sessionStorage.getItem(submitting)) return;sessionStorage.setItem(submitting, true);// 执行提交逻辑 ...});2.4 常见的踩坑点1避免跨标签页依赖通过 window.open() 或 a target_blank 打开新标签页时新标签页的 sessionStorage 为空部