JavaScript怎么读写LocalStorage与SessionStorage

作者:页面旅途时间:2026-11-05 15:40:11浏览:464

详细讲解在JavaScript中读写LocalStorage与SessionStorage的标准方法,涵盖核心API调用、复杂数据对象的JSON序列化处理、配额溢出与异常防护,以及两者生命周期差异与跨标签页通信机制。

Web Storage API 技术主题:前端数据持久化与会话存储 适用环境:现代主流浏览器环境
在前端开发中,LocalStorage 与 SessionStorage 是浏览器原生提供的客户端键值存储方案,统称为 Web Storage API。它们在 JavaScript 中挂载于全局对象 window 下,共用一套简洁的标准读写方法(setItem、getItem、removeItem、clear)。两者的本质区别不在于调用接口,而在于数据的生命周期与隔离作用域。掌握两者的规范读写流程、对象序列化手段以及边界异常处理,能够有效保证客户端数据管理的稳定可靠。
JavaScript怎么读写LocalStorage与SessionStorage
Web Storage API 核心特性与架构概览

一、核心 API 接口与基础读写操作

localStorage 与 sessionStorage 是 Storage 接口的两个不同实例。无论操作哪一个对象,读写接口完全统一。在进行读写时,建议始终调用标准 API,而不是直接通过对象属性访问(例如 localStorage.key = value),因为标准方法能规范化处理保留关键字并确保各浏览器行为一致。

1. 写入数据:setItem(key, value)

使用 setItem() 方法向存储区域添加一个键值对。如果该键已经存在,旧的值会被新值覆盖;如果不存在,则创建新的键值对。

// 向 localStorage 写入用户名与用户偏好
window.localStorage.setItem('username', 'alex_coder');
window.localStorage.setItem('app_theme', 'dark');

// 向 sessionStorage 写入当前页面的临时标签状态
window.sessionStorage.setItem('current_step', 'step_2');

2. 读取数据:getItem(key)

使用 getItem() 方法通过键名获取对应的值。如果指定的键存在,返回对应的字符串值;如果键不存在,则统一返回 null。

// 读取已存储的键
const theme = window.localStorage.getItem('app_theme');
console.log(theme); // 示例输出: "dark"

// 读取未声明的键
const missingItem = window.localStorage.getItem('unknown_key');
console.log(missingItem); // 示例输出: null

3. 删除与清空操作:removeItem(key) 与 clear()

当某些缓存数据失效或用户主动退出登录时,需要及时移除存储数据:

  • removeItem(key):删除指定的单项键值对。若键名不存在,该方法静默处理,不抛出异常。
  • clear():彻底清空当前域名(同源)在当前存储区域下的所有键值对。
// 删除单项数据
window.localStorage.removeItem('username');

// 确认删除结果
console.log(window.localStorage.getItem('username')); // 示例输出: null

// 清空 sessionStorage 全部数据
window.sessionStorage.clear();

4. 遍历与获取总量:length 与 key(index)

Storage 对象还具备 length 只读属性与 key(index) 方法,方便对当前存储的所有项进行完整检查与遍历:

const storage = window.localStorage;
console.log('存储项总量:', storage.length);

for (let i = 0; i < storage.length; i++) {
  const k = storage.key(i);
  const v = storage.getItem(k);
  console.log(`[#${i}] ${k} = ${v}`);
}
JavaScript怎么读写LocalStorage与SessionStorage
图 1:Web Storage 运行时体系架构与多标签页作用域模型

二、处理对象、数组与复杂数据的序列化

Web Storage 的底层实现只接受 UTF-16 DOMString(字符串类型)。如果向 setItem() 传入非字符串值(如对象、数组、数字、布尔值),浏览器会自动调用其内置的 toString() 方法实施隐式类型转换。

⚠️ 隐式转换陷阱:
如果直接执行 localStorage.setItem('user', { id: 1, name: 'Alice' }),存储引擎实际写入的是字符串 "[object Object]"。这不仅丢失了全部属性信息,后续读取也再无法还原。

为了能够准确存储和读取复杂的 JavaScript 实体,必须在写入前使用 JSON.stringify() 进行序列化,并在读取后使用 JSON.parse() 进行反序列化。同时,反序列化过程应当配合 try...catch 进行保护,避免因存储了损坏数据导致整个页面脚本崩溃。

// 1. 定义待存储的复合业务对象
const userProfile = {
  id: 10086,
  name: '张三',
  roles: ['admin', 'editor'],
  lastLogin: new Date().toISOString()
};

// 2. 序列化写入
try {
  const serializedData = JSON.stringify(userProfile);
  window.localStorage.setItem('user_profile', serializedData);
} catch (err) {
  console.error('序列化写入失败:', err);
}

// 3. 安全读取与反序列化还原
function getUserProfile() {
  const rawString = window.localStorage.getItem('user_profile');
  if (!rawString) {
    return null; // 键不存在
  }

  try {
    return JSON.parse(rawString);
  } catch (parseError) {
    console.warn('解析本地存储数据异常,重置为默认值:', parseError);
    return null;
  }
}

const currentUser = getUserProfile();
console.log(currentUser?.name); // 示例输出: "张三"
JavaScript怎么读写LocalStorage与SessionStorage
图 2:Web Storage 数据写入序列化与读取还原处理管道

三、LocalStorage 与 SessionStorage 的特性差异与应用选型

虽然两者在 API 语法上没有差异,但在实际工程架构中,它们的存储位置与生效机制存在明显区别。

1. 数据生命周期(Lifecycle)

  • LocalStorage:属于持久化存储。数据存放在操作系统的本地磁盘数据库中,只要代码没有执行 removeItem 或 clear,且用户未手动清理浏览器缓存,数据就会一直保留,即便关闭浏览器或重启电脑依然存在。
  • SessionStorage:属于临时会话存储。数据保留在当前顶级浏览上下文的内存中。当用户关闭该标签页或关闭浏览器窗口时,对应的存储内容会立即被销毁释放。需要注意,页面刷新(F5 / Reload)不会丢失 SessionStorage。

2. 作用域与标签页隔离(Scope & Isolation)

  • LocalStorage:受同源策略(协议 + 域名 + 端口)约束。同一个源下打开的所有标签页和窗口,全部共享同一份 LocalStorage 数据仓库,任意标签页的修改对其他标签页立即可见。
  • SessionStorage:不仅受同源策略约束,而且严格限制在当前标签页上下文中。在同一个浏览器中打开两个相同网址的独立标签页,它们各自拥有独立的 SessionStorage,互不干扰、互不连通。
技术指标 LocalStorage SessionStorage
存储生命周期 持久保留,直到代码清除或用户清空浏览器数据 仅在当前页面会话有效,关闭标签页即销毁
跨标签页共享 同源下的所有标签页与窗口无缝共享 仅当前标签页独占,同源不同标签页彼此隔离
典型存储容量 约 5MB(同源共享此配额) 约 5MB(每个独立会话独享该配额)
跨页面事件通信 写入会自动向同源其他活跃标签页广播 storage 事件 仅在同页面嵌入的同源 iframe 间触发,不跨标签页
最佳适用场景 用户界面主题设置、系统语言偏好、离线配置、全局状态标记 多步骤注册/下单表单数据草稿、单次会话筛选条件、页内撤销栈
JavaScript怎么读写LocalStorage与SessionStorage
图 3:LocalStorage 与 SessionStorage 特性对比矩阵与选型决策树

四、异常捕获、存储限制与跨标签页通信

1. 存储容量与 QuotaExceededError 异常处理

主流浏览器分配给 Web Storage 的配额一般限制在 5MB 左右(以 UTF-16 字符编码计算,约 250 万到 500 万字符)。当存储内容超过上限,或者用户开启了严苛的私密浏览模式导致写入被拦截时,调用 setItem() 将直接抛出 QuotaExceededError(DOMException 代码 22)。因此,在生产环境中,封装一个健壮的存储访问器必不可少。

/**
 * 健壮的 LocalStorage 安全读写包装器
 */
class SafeLocalStorage {
  // 写入数据(支持对象自动序列化与异常保护)
  static set(key, value) {
    try {
      const payload = JSON.stringify(value);
      window.localStorage.setItem(key, payload);
      return true;
    } catch (error) {
      // 专门识别配额溢出
      if (error.name === 'QuotaExceededError' || error.code === 22) {
        console.error('LocalStorage 存储空间超限,写入已放弃:', key);
      } else {
        console.error('写入本地存储失败:', error);
      }
      return false;
    }
  }

  // 读取数据(支持自动反序列化与默认值降级)
  static get(key, defaultValue = null) {
    try {
      const raw = window.localStorage.getItem(key);
      if (raw === null) return defaultValue;
      return JSON.parse(raw);
    } catch (error) {
      console.warn(`读取键 [${key}] 失败,返回降级默认值:`, error);
      return defaultValue;
    }
  }
}

// 调用示例
SafeLocalStorage.set('user_config', { notify: true, volume: 80 });
const config = SafeLocalStorage.get('user_config', { notify: false });

2. 监听 storage 事件实现跨标签页通信

当任意一个标签页对 localStorage 执行了 setItem()、removeItem() 或 clear() 操作时,浏览器会自动在同源的其他所有打开的标签页中触发 storage 事件。

核心机制提醒:
发起修改操作的当前标签页自身不会触发 storage 事件,只有同源的其他标签页能捕获到该事件。这使得它非常适合用来实现跨标签页的多端状态同步(例如单点登出、实时切换主题等)。
// 在其他标签页中注册监听器
window.addEventListener('storage', (event) => {
  console.log('检测到同源存储发生变更:');
  console.log('被修改的键名:', event.key);
  console.log('原数值:', event.oldValue);
  console.log('新数值:', event.newValue);
  console.log('触发页面的URL:', event.url);

  // 场景示例:全局主题同步
  if (event.key === 'app_theme' && event.newValue) {
    document.body.className = event.newValue;
  }

  // 场景示例:用户在另一窗口登出,本窗口同步刷新或跳转
  if (event.key === 'auth_token' && event.newValue === null) {
    alert('您已在其他窗口退出登录,本页面即将刷新');
    window.location.reload();
  }
});
JavaScript怎么读写LocalStorage与SessionStorage
图 4:StorageEvent 跨标签页广播总线机制与工业级封装结构

五、常见避坑与安全规范

1. 警惕布尔值与空值的真值判断误区

当执行 localStorage.setItem('isVip', false) 时,底层存储的其实是字符串 "false"。在 JavaScript 中,非空字符串 "false" 在隐式布尔转换中判定为真:

localStorage.setItem('isVip', false);

// ❌ 错误判断:字符串 "false" 会被判定为 true!
if (localStorage.getItem('isVip')) {
  console.log('错误:依然被判定为 VIP 用户');
}

// ✔ 正确判断:明确与字符串比较,或者使用 JSON.parse 反序列化
const isVip = localStorage.getItem('isVip') === 'true';
console.log(isVip); // 输出: false

2. 严禁存储敏感身份凭据(防范 XSS 攻击)

Web Storage 中存储的内容对于当前页面同源下的所有 JavaScript 脚本完全可见,且没有任何类似 Cookie 的 HttpOnly 保护标志。一旦网站存在跨站脚本(XSS)漏洞,攻击者可直接通过 localStorage.getItem() 将保存在其中的敏感数据(如用户敏感私钥、身份证号、支付密码、长期凭证等)发送至远程恶意服务器。对于高安全要求的登录会话 Token,应优先使用设置了 HttpOnly 与 Secure 属性的 Cookie 维护。

3. 注意同步阻塞对页面渲染性能的影响

Web Storage 的所有读写操作均在主线程同步执行。这意味着在执行 setItem() 或 getItem() 时,主线程会被阻塞,直到数据写入或读取完毕。如果存储了接近 5MB 的大体积 JSON 字符串,频繁的序列化与磁盘写入会导致动画掉帧和界面卡顿。如果项目需要存储大量结构化数据、二进制文件或大列表,应当选用异步的 IndexedDB。

作者最新文章
相关文章
更多