news 2026/6/25 16:51:01

关于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/23 9:58:38

54、深入解析STREAMS机制:从流头操作到终端控制

深入解析STREAMS机制:从流头操作到终端控制 1. 流头操作:qattach()与qdetach() 当打开一个模块或驱动程序时, qattach() 函数会被调用。其主要作用是为驱动程序或模块设置一个队列对,并调用其 open 函数。 qattach() 的参数之一是一个现有的队列对,新的队列对将链…

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

12、C++ 数据序列化与文件处理实战

C++ 数据序列化与文件处理实战 在 C++ 编程中,数据序列化和文件处理是非常重要的部分。本文将详细介绍如何使用不同的库进行 XML、JSON 数据的序列化和反序列化,以及如何创建包含图像的 PDF 文件和处理 ZIP 归档文件。 1. XML 数据的序列化和反序列化 在 C++ 标准库中,没…

作者头像 李华
网站建设 2026/6/20 19:55:48

三相四桥臂逆变器接不平衡与非线性负载时的调制与控制算法的MATLAB/Simulink仿真模型...

三相四桥臂逆变器MATLAB/Simulink仿真模型,接不平衡负载时的调制算法。 接非线性负载时的多PR控制器并联算法。 提供仿真模型、设计报告及参考文献三相四桥臂逆变器这玩意儿在新能源和微电网里属于硬核装备。接上吹风机、电机这类不平衡负载时,常规的三桥…

作者头像 李华
网站建设 2026/6/25 5:27:27

14、SQLite数据库中电影数据的管理与操作

SQLite数据库中电影数据的管理与操作 1. SQLite简介 SQLite是一个用C语言编写的进程内关系型数据库管理库,它并非客户端 - 服务器数据库引擎,而是嵌入到应用程序中的。整个数据库,包括表、索引、触发器和视图,都包含在一个单一的磁盘文件中。由于访问数据库意味着访问本地…

作者头像 李华
网站建设 2026/6/24 1:28:18

Windows系统文件Windows.Services.TargetedContent.dll缺少损坏问题 下载修复

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…

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

设备预测性维护技术拆解与落地实战

在工业智能化落地进程中,设备预测性维护技术已成为开发者构建智能运维体系的核心抓手。但实际开发中,多数团队面临“协议适配难、算法落地繁、系统对接贵”的痛点——某自动化团队为适配10种品牌设备,花费3个月开发协议解析模块;某…

作者头像 李华