localStorage 与 sessionStorage
发布于 更新于
一句话: localStorage 与 sessionStorage 都是暴露在 Window 上的同步、仅存字符串、
同源的键值存储;localStorage 会跨标签页和浏览器重启持久保存,而 sessionStorage 只作用于
单个标签页,在该标签页关闭时被清除。
localStorage.setItem("theme", "dark");const theme = localStorage.getItem("theme"); // "dark"localStorage.removeItem("theme");localStorage.clear(); // 移除该源下的所有键
// sessionStorage 拥有完全相同的方法集,作用范围为当前标签页:sessionStorage.setItem("draftId", "42");根据 MDN 的使用指南,两个接口都只存储字符串——对象或数组等非字符串数据必须显式转换,
例如使用 JSON.stringify()。
浏览器支持与配额
Section titled “浏览器支持与配额”localStorage 与 sessionStorage 都是 Web Storage API 中历史悠久、被广泛实现的部分,
在当前主流浏览器中均可用。根据 MDN,二者是各自独立的 Storage 对象,“function and are
controlled separately”(各自独立运作和控制)。根据 MDN 的使用指南,当该源可用的存储空间
全部用尽后,写入仍可能失败,此时会抛出 QuotaExceededError 这一 DOMException,而不是
静默失败。
响应其他标签页的变化
Section titled “响应其他标签页的变化”window.addEventListener("storage", (event) => { console.log(event.key, event.oldValue, event.newValue);});storage 事件会在 localStorage 发生变化时,触发在共享同一存储区域的其他 Document
上——绝不会触发在发起变更的那个 document 自身。根据 MDN,这意味着同一标签页中其他同源的
document(例如一个 iframe)仍可能收到该事件,即使发起写入的 document 不会。可用它来保持
其他已打开的 document 之间的同步。
如何在运行时检测
Section titled “如何在运行时检测”function storageAvailable() { if (!('localStorage' in window)) { // localStorage 属性不存在 —— 回退到本次会话的内存存储。 return false; } try { const probe = "__storage_test__"; window.localStorage.setItem(probe, probe); window.localStorage.removeItem(probe); return true; } catch { // 接口存在但不可用——例如某些隐私浏览模式会报告 0 字节配额——因此视为 // 不可用,并采用相同的回退方式。 return false; }}这与 MDN 自身在“Using the Web Storage API”中给出的特性检测方法类似,同样通过一次真实
写入来探测——不过 MDN 的版本会把已有数据的存储上抛出的 QuotaExceededError 视为存储
仍然可用的证据,而不是像上面这个简化探测那样,一旦捕获异常就无条件判定为不可用。
- 值始终是字符串——存入结构化数据前先用
JSON.stringify(),取出后用JSON.parse()。 - 两者都是同源的:协议、主机、端口必须全部一致,因此
https://example.com与http://example.com不共享存储。 -
storage事件只会在共享存储区域的其他 document 上触发,绝不会在发起写入的那个 document 上触发——不要在本地等待它。根据 MDN,同一标签页中其他同源的 document (例如一个 iframe)仍可能收到该事件。 - 隐私/无痕模式下的行为在各浏览器间并不一致。根据 MDN 的 Web Storage 指南,
在隐私窗口中写入的数据通常会被当作
sessionStorage处理,在最后一个隐私 标签页关闭时被清除——但 MDN 同时指出,部分浏览器会改为暴露一个配额固定为 0 字节的localStorage对象,写入会立即抛出,而不是保留到标签页关闭。 应通过真实的写入/删除探测来做特性检测,而不是假设某一种行为。 - 所有读写都是同步的,并运行在主线程上;较大的值或频繁写入会阻塞渲染—— 对于体量较大的数据应优先使用 IndexedDB。
- 根据 MDN,
sessionStorage是按源与顶层浏览上下文共同划分的——并不只是简单地 “每个标签页一份”。根据 MDN,一个持有opener(指向打开它的那个页面)引用的 新页面,在初始时会获得该 opener 的sessionStorage副本;没有 opener 的 上下文则不会。
- 存储持久化、配额与驱逐 —— 与源存储配额相关 的参考条目。
- 清除站点数据 —— 与清除站点存储相关的 参考条目。