F13第 1 / 1 课时未开始内容版本 1.0.0 · 核验于 2026-10-26

浏览器存储与序列化

浏览器存储与序列化 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。

学习目标

这一课给应用加上「记忆」:用 localStorage(浏览器提供的本地键值存储)保存主题和表单草稿,用 JSON 序列化(把对象变成字符串存起来、再还原的过程)存取结构化数据。读完你应该能安全处理坏数据、版本升级和写入失败这三类存储事故,并且知道为什么它不能当可靠备份。

问题场景

你的课程页有夜间模式,用户切到深色,刷新一下又变回白色;评论区打了两百字,误触刷新全没了。加存储时更糟:用户手动改过 localStorage 里的值,或者旧版本代码存过旧格式,JSON.parse 直接抛异常,初始化代码崩掉,整页白屏。存储代码的功夫,全在「不信任读回来的数据」。

核心解释

localStorage 只能存字符串,对象要经过 JSON 序列化往返:

// 存:对象 → 字符串
localStorage.setItem('theme', JSON.stringify({ mode: 'dark', fontSize: 16 }));

// 读:字符串 → 对象(可能抛错!)
const raw = localStorage.getItem('theme');
const theme = raw ? JSON.parse(raw) : { mode: 'light', fontSize: 14 };

三个必须防的场景,各有标准动作:

  1. 坏数据:JSON.parse 遇到非法字符串会抛异常。读写都包 try/catch,解析失败就当没有,回退默认值。
  2. 版本升级:数据结构变了(比如旧版没有 fontSize)。存的时候带版本号,读的时候版本不符就迁移或丢弃:
const KEY = 'theme';
const VERSION = 2;

function loadTheme() {
  try {
    const raw = localStorage.getItem(KEY);
    if (!raw) return null;
    const data = JSON.parse(raw);
    if (data.version !== VERSION) return migrate(data); // 旧版本先迁移
    if (typeof data.mode !== 'string') return null; // 形状不对就丢弃
    return data;
  } catch {
    return null; // 坏数据当没有
  }
}
  1. 写入失败:隐私模式、配额(一般 5MB 左右)占满时,setItem 会抛异常。保存失败要提示用户,不能假装成功。

示例拆解

一个「保存草稿」的最小封装,把防线都装进去:

function saveDraft(text) {
  try {
    localStorage.setItem('draft', JSON.stringify({ version: 1, text, at: Date.now() }));
    return true;
  } catch {
    return false; // 配额满或隐私模式:由调用方决定怎么提示
  }
}

window.addEventListener('beforeunload', () => saveDraft(input.value));
  • 恢复草稿用同一套读法:读 → parse(包 try/catch)→ 校验字段 → 使用。
  • 「缓存」和「备份」的区别要刻在脑子里:localStorage 可能被用户清掉(清除站点数据)、被隐私模式禁用、换浏览器就没有。它适合偏好、草稿这类「丢了不心疼」的数据;用户认真写的内容该发往服务器入库,别只存本地。
  • 验证读失败:开发者工具的 Application(存储)面板,手动把某个值改成乱码再刷新,页面应该照常打开。

动手任务

打开本课实验区:

  1. 给实验区的 theme 数据加 fontSize 字段、把 VERSION 升到 2,运行后观察 v1 旧数据被迁移的日志。
  2. 点「模拟坏数据」按钮把存储写成非法 JSON,再点「读取」,确认输出是回退值而不是异常。
  3. 给 saveDraft 写调用方:保存失败时在页面显示「当前环境无法保存」的提示。

常见错误

  • 裸写 JSON.parse 不包 try/catch:一个坏值让初始化代码崩掉、整页白屏;存储是外部输入,按不信任处理。
  • 存对象忘了 stringify:setItem('k', { a: 1 }) 会被隐式转成 "[object Object]",读回来永远解析不了。
  • 结构升级不迁移:新版读到旧数据直接丢弃,用户偏好全部重置;带版本号是底线。
  • 把 localStorage 当数据库或备份:容量小、可被清空、不跨设备同步;只放「丢了可恢复」的数据。

检查与复盘

完成下方检查题确认理解。自查清单:

  • 读写 localStorage 有固定套路:try/catch + 版本号 + 字段校验
  • 能演示「存进去一个坏值,页面依然正常」
  • 能说清哪些数据适合放本地、哪些必须上服务器

参考资料

动手实验
动手实验
预览
点击「运行」在隔离沙箱中预览
检查题共 2 题,提交后立即显示解析
答案由服务端判定;答错的题会自动进入复习计划。
Q1故障定位中等

bug 现场:页面刷新后「已保存的待办」全部消失,控制台报 Uncaught SyntaxError: Unexpected token 'u'。读写代码如下,问题在哪、怎么修?

function saveTodos(todos) {
  localStorage.setItem('todos', todos);
}

function loadTodos() {
  return JSON.parse(localStorage.getItem('todos')) || [];
}
Q2多选中等(多选,全部选对才算正确)

关于浏览器端存储,下列说法正确的有哪些?(多选)

读完这一课了?

标记完成后,工作台会安排接下来的学习。

Command Palette

Search for a command to run...