news 2026/7/9 16:23:12

关于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/7/10 10:42:18

JoyAgent-JDGenie系统架构设计

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

作者头像 李华
网站建设 2026/7/10 10:41:29

关于javaSE异常的处理(看这一篇就够了)

目录 一、异常是什么 1.异常的概念 2.异常的分类 二、异常的处理 1.防御式编程 2.(异常的抛出)throw的使用 3.异常的声明-throws 4.捕获异常-try-catch捕获并处理异常 5.finally关键字起到 三、异常的处理流程 四、总结 一、异常是什么 1.异常…

作者头像 李华
网站建设 2026/7/9 21:25:28

使用 deepseek 快速搭建 TDengine IDMP demo

背景 TDengine IDMP 产品的客户多为工控场景。在工控体系中,系统自下而上通常划分为现场设备层、现场控制层、过程监控层、生产管理层以及企业资源层。因此,最初的数据来源于现场设备层,这些数据也是后续所有业务驱动的来源。对于TDengine而…

作者头像 李华
网站建设 2026/7/10 10:45:12

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

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

作者头像 李华
网站建设 2026/7/9 22:31:26

Python property魔法:让属性访问变得智能又安全

一、property基础:从数据封装开始 1.1 为什么需要属性封装? 在面向对象编程中,数据封装是基本原则之一。直接暴露属性可能导致数据不一致和逻辑错误。 # 问题示例:直接访问导致数据不一致 class BankAccount:def __init__(self, b…

作者头像 李华
网站建设 2026/7/10 10:42:21

基于Java Swing的打砖块小游戏(2)

1、演示视频 基于Java Swing的打砖块小游戏2、项目截图 设计说明 3.1 整体架构设计 项目采用分层设计面向对象封装的架构&#xff0c;主要分为以下几个部分&#xff1a; 界面层&#xff08;UI层&#xff09;&#xff1a;由<代码开始>BreakoutGame<代码结束>类中…

作者头像 李华