浏览器缓存之【基础键值存储】:Local storage 和 Session storage

〇、前言

虽然在日常口语中我们常把浏览器中 Application -> Storage 模块中的多种类型统称为"浏览器缓存",但在计算机科学与 Web 开发的专业定义中,实际上包含了**"存储"** 与**"缓存"**两个截然不同但又紧密相关的概念体系。

其中本文将着重介绍的 Local storage 和 Session storage 就属于应用数据存储体系。这部分机制的主要目的是持久化保存数据(如:用户设置、登录状态、业务记录),以便在页面刷新或重启后恢复应用状态。它们通常由 JavaScript 代码主动读写。

LocalStorage 用于长期保存(如:主题偏好),SessionStorage 仅在当前标签页会话有效(如:表单草稿)。它们不是用来加速网页加载的,而是为了记住用户的数据。

下边是详细介绍,供参考。

一、什么是 LocalStorage?

1.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 MB

Firefox:约 5--10 MB

Safari(iOS):可能低至 1 MB(内存紧张时更低)

微信 WebView(X5 内核):常不足 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),需降级处理。

二、什么是 SessionStorage?

2.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 为空**(部分浏览器可能复制旧数据,但属于非规范行为,不可依赖)**。

2)隐身/隐私模式的特殊行为

部分浏览器完全禁用: Chrome 等在隐身模式下会抛出 SecurityError(调用 setItem() 时),需通过 try-catch 降级处理4。

**Safari 的差异:**在隐私浏览模式下,sessionStorage 可写入但关闭标签页后数据立即失效(符合规范)。

3)与"缓存"概念的常见误区

非 HTTP 缓存:SessionStorage 不参与浏览器缓存流程 (如:Cache-Control),与资源加载速度无关。

非服务端会话:其名称中的 "session" 仅指浏览器标签页的生命周期,不关联服务端 Session 机制(如:PHP 的 $_SESSION)。

三、两者的关系和区别

LocalStorage 和 SessionStorage 同属 Web Storage API,核心区别在于数据生命周期与作用域:

  • LocalStorage 采用永久存储机制,数据除非手动清除否则长期保留;
  • SessionStorage 采用会话级存储机制,数据仅在当前标签页会话期间有效,关闭标签页后自动清除。

两者均基于同源策略,提供相同的键值对操作接口,且数据不会随 HTTP 请求发送至服务器,避免了 Cookie 的带宽浪费问题。

3.1 LocalStorage 和 SessionStorage 的相同点

基础机制方面的相同点:

同属 Web Storage 规范:两者均为 HTML5 定义的客户端存储方案,用于替代 Cookie 实现更高效的本地数据存储

存储形式一致:均以字符串键值对形式存储数据 ,复杂对象需通过 JSON.stringify() 和 JSON.parse() 转换。

API 接口相同:均提供setItem()、getItem()、removeItem()、clear() 和 key() 等方法,操作逻辑完全一致。

同源策略限制:数据仅对相同协议、域名、端口的页面可见,跨源无法访问。

相同的性能优势:

避免网络传输:与 Cookie 不同,存储数据不会随 HTTP 请求自动发送至服务器,显著减少冗余流量。

容量更大:理论存储上限普遍为 5MB~10MB(具体因浏览器而异),远高于Cookie 的 4KB 限制。

本地快速读取:数据直接从浏览器缓存读取,无需网络请求,提升页面响应速度。

3.2 LocalStorage 和 SessionStorage 的区别

特性 LocalStorage SessionStorage
生命周期 永久存储,除非手动清除或用户主动删除 会话级存储,关闭标签页后自动清除
作用域 同源窗口间全局共享(所有标签页可见) 仅当前标签页有效,不同标签页独立隔离
典型场景 用户偏好设置、持久化缓存、跨页面数据共享 临时表单数据、页面跳转状态、敏感操作流程
关闭浏览器后 数据保留 数据清除
隐私模式 不可读取 不可读取

LocalStorage 和 SessionStorage 通过差异化生命周期设计,分别解决了持久化缓存与临时状态管理的需求。**若需数据跨会话留存,选 LocalStorage;若仅需单次会话内有效,选 SessionStorage。**两者结合同源策略与高效 API,成为现代 Web 应用客户端存储的核心基础设施。

四、小小的总结

LocalStorage 和 SessionStorage 作为 Web Storage API 的核心成员,共同构成了现代 Web 应用客户端数据存储的基础设施。它们通过标准化的键值对接口,解决了传统 Cookie 在容量与性能上的局限,成为替代 Cookie 实现高效本地存储的首选方案。

  • 核心定位:应用状态管理,而非网络加速

二者本质上属于应用数据存储体系,而非 HTTP 缓存机制。其核心价值在于持久化保存用户数据(如偏好设置、登录状态、业务记录),以便在页面刷新或重启后恢复应用状态,而非加速资源加载。

关键差异:生命周期决定应用场景

  LocalStorage:采用永久存储机制,数据除非手动清除否则长期保留,适用于跨会话的持久化需求(如用户主题偏好、长期缓存)。

  SessionStorage:采用会话级存储机制,数据仅在当前标签页会话期间有效,关闭标签页后自动清除,适用于单次会话的临时状态管理(如表单草稿、页面跳转状态)。

  • 共同约束:同源策略与安全边界

两者均严格遵循同源策略(协议+域名+端口),且数据不会随 HTTP 请求发送至服务器,避免了 Cookie 的带宽浪费问题。

但需注意:

  仅支持字符串存储,复杂对象需序列化。

  容量限制约 5--10 MB(实际因浏览器而异)。

  避免存储敏感信息(如未加密的 token),防范 XSS 攻击风险。

  • 实践指引:按需选择,规避陷阱

选 LocalStorage:当数据需跨会话留存、跨标签页共享时。

选 SessionStorage:当数据仅需单次会话有效、标签页隔离时。

避坑要点:

  • 写入前检测容量余量,捕获 QuotaExceededError。

  • 隐身模式下可能完全禁用,需降级处理。

  • 敏感操作优先使用 HttpOnly Cookie 或服务端会话。

通过合理运用这两种存储机制,开发者可在保障安全的前提下,显著提升 Web 应用的用户体验与响应效率,构建更智能、更可靠的客户端数据管理方案。

相关推荐
mldong4 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排4 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60615 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角6 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!6 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰6 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi8 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen8 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马9 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒9 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端