在纯前端开发中,经常需要把一些轻量数据留在用户浏览器里,比如记住用户名、暂存未提交的表单、保存界面主题。HTML5给出的Web Storage方案包含两个对象:localStorage与sessionStorage。它们都挂在window下,用起来很相似,但数据存活时间和可见范围完全不同。下面先通过一张示意图建立直观认识,然后逐一拆解用法与差异。

一、基本API与写入读取
无论是localStorage还是sessionStorage,暴露的方法都是同一套:setItem、getItem、removeItem、clear,以及直接通过方括号或点语法赋值。数据必须以字符串形式存储,所以对象通常需要先用JSON.stringify转换。
下面这段代码演示了如何用localStorage保存一个用户对象,并在下次打开页面时读出来。注意捕获异常,因为在隐私模式或超出配额时写入会抛错。
try {
var user = { name: '张三', uid: 1001 };
localStorage.setItem('cur_user', JSON.stringify(user));
var raw = localStorage.getItem('cur_user');
if (raw) {
var obj = JSON.parse(raw);
console.log('读取到用户:', obj.name);
}
// 删除单个键
localStorage.removeItem('cur_user');
// 清空所有
localStorage.clear();
} catch (e) {
console.warn('本地存储不可用或写入失败', e);
}
sessionStorage的写法完全一样,只要把上面代码里的localStorage换成sessionStorage即可。因为接口一致,很多封装函数会接收一个storage对象作为参数,从而同时支持两种存储。
从工程角度看,建议统一封装一个storage工具模块,内部判断环境并自动做JSON转换与异常兜底,业务层就不需要关心当前用的是哪种存储。这样也方便后续切换到IndexedDB等更复杂的方案。
二、生命周期与作用域区别
二者最本质的差别在于生命周期。localStorage的数据写入后,除非代码主动删除,或者用户手动在浏览器设置里清除,否则永远存在,跨会话、跨重启浏览器都在。sessionStorage则绑定于单个标签页的会话:同一标签页刷新页面数据还在,但一旦关闭标签页,数据就被浏览器回收。
作用域方面,localStorage在同源(协议、域名、端口相同)的所有标签页、窗口之间共享;sessionStorage虽然同源,但只在同一个标签页内可见,哪怕打开同一个网站的新标签页,也看不到旧标签页里的sessionStorage。这一特性常用来避免多标签页之间的表单状态互相干扰。
| 对比项 | localStorage | sessionStorage |
|---|---|---|
| 生命周期 | 永久,需手动清除 | 标签页关闭即清除 |
| 共享范围 | 同源所有窗口共享 | 仅当前标签页 |
| 典型用途 | 记住登录令牌、偏好设置 | 单页表单暂存、步骤向导 |
举个例子,如果用户在一个标签页登录后,localStorage里存了token,那么新开的同源标签页也能直接拿到token保持登录态。但如果是sessionStorage存token,用户新开标签页就需要重新登录,因为旧会话的存储不可见。
需要特别注意的是,某些浏览器在恢复标签页(如崩溃后重新打开)时,可能会保留sessionStorage,这不属于规范强制行为,不能依赖。关键业务数据不要假设sessionStorage一定随关随清。
三、storage事件与跨页同步
当同源页面修改了localStorage,其他同源且处于打开状态的页面会收到一个storage事件。这个事件不会在修改数据的那个页面自身触发,因此非常适合做多标签页之间的状态广播。
下面的例子展示了在页面A修改localStorage后,页面B如何监听变化并更新界面。sessionStorage的修改不会触发storage事件,这是它和localStorage另一个行为差异。
// 在页面B中监听
window.addEventListener('storage', function (event) {
if (event.key === 'theme') {
console.log('主题变更为', event.newValue);
document.body.className = event.newValue;
}
});
// 在页面A中修改
localStorage.setItem('theme', 'dark');
利用这个机制,可以实现购物车数量同步、深色模式全局切换等体验优化。但要注意storage事件里的oldValue和newValue都是字符串,复杂结构仍需自行解析。
由于sessionStorage不触发storage事件,如果需要在单页应用内跨组件通信,应该优先使用框架自身的状态管理,而不是指望存储事件。
四、容量限制与和Cookie的对比
主流浏览器给单个源的Web Storage容量一般是5MB左右,比Cookie的4KB大很多,而且不会随每个HTTP请求自动发送到服务器,能减轻带宽压力。Cookie适合存认证凭据且需要服务端读取的场景,localStorage和sessionStorage更适合纯客户端的状态保留。
当存储超出限额时,setItem会抛出QuotaExceededError,所以生产代码一定要用try-catch包裹。另外,隐私浏览模式下部分浏览器会把存储设为只读或临时隔离,也不能假设一定能写成功。
function safeSet(storage, key, val) {
try {
storage.setItem(key, val);
return true;
} catch (err) {
console.error('写入失败,可能配额满或隐私限制', err);
return false;
}
}
safeSet(sessionStorage, 'draft', '未完成的内容');
从安全角度,任何敏感信息都不建议明文放在本地存储里,因为同源下的任意脚本都能读取,一旦遭遇XSS攻击就会泄露。登录凭证尽量用HttpOnly Cookie,本地存储只放非敏感的偏好或缓存。
总结来看,实现JavaScript本地存储就是熟练使用那几个API,而选型时抓住两点:要永久且多页共享就用localStorage,仅当前会话临时用就用sessionStorage。明确边界,才能写出稳妥的前端存储逻辑。
JavaScriptlocalStoragesessionStorage修改时间:2026-08-03 07:42:28