news 2026/6/10 13:13:13

关于JS中的全部存储方式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
关于JS中的全部存储方式

一、为什么需要 JS 客户端存储?

HTTP 协议的无状态特性导致浏览器与服务器每次通信都无法保留上下文,而客户端存储正是解决这一痛点的关键:

  1. 状态保持:记住用户登录状态、购物车数据、表单填写进度
  1. 性能优化:缓存接口数据、静态资源,减少网络请求(尤其弱网场景)
  1. 离线能力:支持 PWA 离线访问、本地文档编辑等场景
  1. 个性化体验:存储用户偏好(主题、字体大小)、浏览历史

核心需求本质是:在浏览器端安全、高效地存储不同生命周期、不同容量级别的数据

二、JS 客户端存储全景图

JS 客户端存储主要分为 5 大类,覆盖从 1KB 到 GB 级的存储需求,适用场景各有侧重:

存储方案

容量限制

生命周期

同源策略

访问权限

核心特性

Cookie

4KB

可配置(Expires/Max-Age)

前后端均可访问

随 HTTP 请求自动携带,支持跨域配置

localStorage

5-10MB

永久(手动清除)

仅前端访问

同步操作,字符串键值对

sessionStorage

5-10MB

会话级(标签页关闭失效)

仅前端访问

同标签页共享,刷新不丢失

IndexedDB

无明确限制(取决于磁盘)

永久

仅前端访问

异步操作,支持结构化数据、事务

Cache API

无明确限制

永久(手动清除)

仅前端访问

专门缓存 HTTP 请求 / 响应

三、逐个击破:每种存储方案的实战指南

1. Cookie:前后端共享的 “轻量存储”

核心原理

Cookie 是服务器发送给浏览器的小型文本数据,浏览器会在后续请求中自动携带(通过Cookie请求头),常用于身份验证、会话跟踪。

关键 API 与配置

// 设置Cookie(核心参数:键、值、过期时间、域名、路径、安全属性)

function setCookie(key, value, options = {}) {

let cookieStr = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;

// 过期时间:Expires(日期字符串)或 Max-Age(秒数)

if (options.expireDays) {

const date = new Date();

date.setTime(date.getTime() + options.expireDays * 24 * 60 * 60 * 1000);

cookieStr += `; Expires=${date.toUTCString()}`;

}

// 核心安全属性(必设!)

cookieStr += `; Path=${options.path || '/'}`; // 生效路径

cookieStr += options.domain ? `; Domain=${options.domain}` : '';

cookieStr += options.secure ? '; Secure' : ''; // 仅HTTPS传输

cookieStr += '; SameSite=Lax'; // 防御CSRF攻击

cookieStr += options.httpOnly ? '; HttpOnly' : ''; // 禁止JS访问(防XSS)

document.cookie = cookieStr;

}

// 读取Cookie

function getCookie(key) {

const cookies = document.cookie.split('; ');

for (const cookie of cookies) {

const [k, v] = cookie.split('=');

if (decodeURIComponent(k) === key) {

return decodeURIComponent(v);

}

}

return null;

}

// 删除Cookie(设置过期时间为过去)

function removeCookie(key) {

setCookie(key, '', { expireDays: -1 });

}

适用场景与坑点

✅ 适用:身份令牌(JWT)、会话 ID、记住登录状态(7 天免登录)

❌ 不适用:大量数据(4KB 限制)、敏感数据(即使有 HttpOnly,仍可能被 CSRF 利用)

⚠️ 坑点:

  • 每次 HTTP 请求都会携带所有 Cookie,增加带宽消耗(建议核心 Cookie 仅保留 1-2 个)
  • 跨域请求默认不携带 Cookie,需配置withCredentials: true(前端)+ Access-Control-Allow-Credentials: true(后端)

2. Web Storage:前端专属的 “键值对存储”

localStorage和sessionStorage统称 Web Storage,API 完全一致,核心差异在生命周期和共享范围。

核心 API(通用)

// 存储数据(自动转为字符串,复杂数据需序列化)

localStorage.setItem('username', 'zhangsan');

localStorage.setItem('userInfo', JSON.stringify({ id: 1, age: 20 }));

// 读取数据

const username = localStorage.getItem('username');

const userInfo = JSON.parse(localStorage.getItem('userInfo'));

// 删除数据

localStorage.removeItem('username');

localStorage.clear(); // 清空所有

// 遍历数据

for (let i = 0; i ++) {

const key = localStorage.key(i);

console.log(key, localStorage.getItem(key));

}

两者核心差异

特性

localStorage

sessionStorage

生命周期

永久(除非手动清除)

标签页关闭后失效

共享范围

同源所有标签页

仅当前标签页

跨窗口通信

支持(storage 事件)

不支持

进阶封装:带过期时间的 Web Storage

原生 Web Storage 不支持过期时间,封装工具类解决这一痛点:

class StorageUtil {

constructor(storage = localStorage) {

this.storage = storage;

}

// 存储数据(expire:过期时间,单位秒,0表示永久)

set(key, value, expire = 0) {

const data = {

value,

expire: expire ? Date.now() + expire * 1000 : 0,

timestamp: Date.now()

};

this.storage.setItem(key, JSON.stringify(data));

}

// 读取数据(自动清理过期数据)

get(key) {

const json = this.storage.getItem(key);

if (!json) return null;

try {

const data = JSON.parse(json);

// 检查过期

if (data.expire && data.expire {

this.remove(key);

return null;

}

return data.value;

} catch (e) {

this.remove(key); // 数据格式错误时清理

return null;

}

}

remove(key) {

this.storage.removeItem(key);

}

clear() {

this.storage.clear();

}

// 监听storage变化(仅localStorage有效)

onStorageChange(callback) {

window.addEventListener('storage', (e) => {

callback({

key: e.key,

oldValue: e.oldValue ? JSON.parse(e.oldValue)?.value : null,

newValue: e.newValue ? JSON.parse(e.newValue)?.value : null,

storageArea: e.storageArea

});

});

}

}

// 实例化

const localStore = new StorageUtil(localStorage);

const sessionStore = new StorageUtil(sessionStorage);

// 使用示例

localStore.set('token', 'xxx', 86400); // 24小时过期

console.log(localStore.get('token'));

适用场景与坑点

✅ 适用:

  • localStorage:用户偏好设置、表单缓存、非敏感接口数据缓存
  • sessionStorage:临时表单数据、页面间临时传值(同标签页)

❌ 不适用:

  • 大量数据(5-10MB 限制)
  • 敏感数据(易被 XSS 攻击窃取)
  • 跨标签页实时通信(sessionStorage 不支持,localStorage 需监听 storage 事件)

⚠️ 坑点:

  • 同步操作:批量读写会阻塞主线程(建议单次存储不超过 100KB)
  • 字符串序列化:存储undefined会转为"undefined",存储循环引用对象会报错
  • 同源限制
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 11:55:19

JoyAgent-JDGenie系统流程图

系统流程图 📌 查看流程图说明 本文档使用 Mermaid 语法绘制流程图。如果流程图无法正常显示,请使用以下方式查看: VS Code: 安装 “Markdown Preview Mermaid Support” 扩展 GitHub/GitLab: 直接查看,自动支持 Mermaid 在线编辑器: 访问 Mermaid Live Editor 复制代码查…

作者头像 李华
网站建设 2026/6/10 11:51:33

不需要下载夸克直链网盘下载-在线免费工具

2025年12月最新今天教大家一招能解决夸克网盘限制的在线工具。这个工具也是完全免费使用的。下面让大家看看我用这个工具的下载速度咋样。地址获取:放在这里了,可以直接获取 这个速度还是不错的把。对于平常不怎么下载的用户还是很友好的。下面开始今天的…

作者头像 李华
网站建设 2026/6/10 11:49:20

53、STREAMS 流处理机制深度解析

STREAMS 流处理机制深度解析 1. I_PUSH 操作 I_PUSH 是 strioctl 的一部分,其主要作用是将模块推入流中。以下是其详细处理流程: 1. 资源检查 :检查 STREAMS 内存和已推入模块的数量,如果出现错误则直接返回。 2. 模块名称检查 :确认模块名称是否存在于 fmodsw 中…

作者头像 李华
网站建设 2026/6/10 11:53:45

8、C++算法与数据结构实用案例解析

C++算法与数据结构实用案例解析 在C++编程中,算法和数据结构是核心内容,它们能帮助解决各种实际问题。本文将介绍多个实用算法和数据结构的实现,包括电话号码规范化、字符串排列生成、电影平均评分计算、配对算法、压缩算法、选择算法、排序算法以及图中最短路径查找等,同…

作者头像 李华
网站建设 2026/6/10 4:24:47

58、深入理解信号量:原理、使用与实现

深入理解信号量:原理、使用与实现 1. 信号量控制命令 信号量的操作通过一系列控制命令实现,这些命令为进程间通信提供了强大的支持。以下是常见的信号量控制命令: - SETVAL :将信号量的值设置为参数 arg.value 中的值。 - GETPID :返回 semid ds 中的 sempid…

作者头像 李华
网站建设 2026/6/10 12:31:50

63、系统崩溃分析与内核栈深入解析

系统崩溃分析与内核栈深入解析 1. 信号相关机制与状态 在系统运行过程中,存在一些关键的信号相关机制和状态信息。例如, sigflag 和 oldmask 与 w sigflag 字段的值相关。若该字段非零,表明进程此前执行过 sigsuspend 系统调用,正等待信号。 w sigoldmask 字段…

作者头像 李华