给localStorage设置一个过期时间的方法分享
本文探讨如何在HTML5 localStorage中实现数据过期机制。通过重写setItem、getItem和remove方法,利用时间戳判断数据有效性,并处理JSON序列化问题。文章提供了完整的JavaScript类封装示例,帮助开发者解决localStorage无法原生设置过期时间的痛点,提升Web应用数据管理的灵活性。
localStorage过期机制的背景与需求
思考点
在Web开发领域,常见的用户数据持久化方案包括Cookie、Session和localStorage。Cookie通过domain和path属性限制访问范围,存在数量和大小限制,且支持设置有效期限。Session机制由后端在浏览器注入带有httponly标志的不可读Cookie,会话数据通常存储于后端数据库或内存中,通过Cookie中的唯一标识符维持状态,同样支持过期时间设置。相比之下,localStorage作为HTML5提供的数据存储方案,虽然具备较大的存储空间,但原生API并不支持直接设置过期时间。
从前端开发的初期接触,我们便熟悉Cookie或Session等存储机制。为了更直观地理解“过期”概念,可以类比生活中的常见场景:
- Cookie在创建时即可指定有效期,若未显式设置,则默认在浏览器会话结束时失效;
- 以淘宝购物为例,下单付款后系统会设定一个收货期限,超过该时间未确认收货则自动视为完成交易(即订单生命周期结束);
- 闹钟设定的提醒时刻,本质上也是该任务的一个过期时间节点;
- 再如日常产品需求,从立项到最终上线的时间节点,即为该需求的有效期;
- 通俗而言,今年生日至明年生日之间的时间段,也可视为一种有效期设定;
综上所述,任何事件或行为都对应特定的时间节点。既然Session和Cookie均具备完善的过期机制,为何localStorage作为功能完备的API却无法原生支持?原因在于现有存储方案往往无法满足实际业务中对长期缓存且需自动清理的需求。
实现思路与核心逻辑
实现思路
前文关于“黑”localStorage的说法略显夸张,但核心问题已明确:如何为localStorage添加过期时间机制?接下来将展示具体实现方案。
方法重写与代码实现
简单回顾
//示例一:
localStorage.setItem('test',1234567);
let test = localStorage.getItem('test');
console.log(typeof test, test);
//示例二:
localStorage['name'] = '苏南';
console.log(localStorage['name']);
/*
输出:
"1234567" ,'苏南',
这里要注意,1234567 存进去时是number 取出来就成string了
*/
我们需要重写localStorage的set方法以支持过期时间参数。
- 该方法接收三个参数:key(键名)、value(值)以及expired(过期时间);
- 过期时间的单位可根据实际需求灵活定义,如小时、分钟或天;
- 需注意:若存储值为数组或对象,必须通过JSON.stringify转换为字符串后再存入;
- 时间戳的设置策略为:在原有key基础上扩展一个字段(如key+'expires'),其值为当前时间戳加上设定的过期时间毫秒数。
具体来看一下代码 :
set(key, value, expired) {
/*
* set 存储方法
* @ param {String} key 键
* @ param {String} value 值,
* @ param {String} expired 过期时间,以分钟为单位,非必须
* @ 由@IT·平头哥联盟-首席填坑官∙苏南 分享
*/
let source = this.source;
source[key] = JSON.stringify(value);
if (expired){
source[`${key}__expires__`] = Date.now() + 1000*60*expired
};
return value;
}
同时需要重写get方法以支持过期判断。
- 获取数据时,首先检查之前存储的有效期字段,并与当前时间进行对比;
- 由于expired参数在存储时非必填,若未设置,则默认值为当前时间加1,即视为长期有效;
- 若存储时设置了过期时间,且在获取时发现当前时间已超过该时间戳,则执行删除操作并返回空值;
- 注意:若存储值为数组或对象,取出后需通过JSON.parse转换回原始数据结构后再返回;
具体来看一下代码 :
get(key) {
/*
* get 获取方法
* @ param {String} key 键
* @ param {String} expired 存储时为非必须字段,所以有可能取不到,默认为 Date.now+1
* @ 由@IT·平头哥联盟-首席填坑官∙苏南 分享
*/
const source = this.source,
expired = source[`${key}__expires__`]||Date.now+1;
const now = Date.now();
if ( now >= expired ) {
this.remove(key);
return;
}
const value = source[key] ? JSON.parse(source[key]) : source[key];
return value;
}
此外,还需重写remove方法以同步清理过期标记。
删除操作相对简单,主要涉及数据键及其对应的过期时间键的清理;
remove(key) {
const data = this.source,
value = data[key];
delete data[key];
delete data[`${key}__expires__`];
return value;
}
性能优化与注意事项
优化点:
- 曾有开发者评论:“删除缓存能否放在constructor中执行?若放在get中,不读取数据则垃圾数据一直存在,是否影响性能?”;
- 关于遍历方式的选择:为何不使用for...in循环?因为for...in会遍历对象原型链上的所有属性,解决方案是使用hasOwnProperty方法过滤或Object.keys返回自身可枚举属性组成的数组;
class storage {
constructor(props) {
this.props = props || {}
this.source = this.props.source || window.localStorage
this.initRun();
}
initRun(){
/*
* set 存储方法
* @ param {String} key 键
* @ param {String} value 值,存储的值可能是数组/对象,不能直接存储,需要转换 JSON.stringify
* @ param {String} expired 过期时间,以分钟为单位
* @ 由@IT·平头哥联盟-首席填坑官∙苏南 分享
*/
const reg = new RegExp("__expires__");
let data = this.source;
let list = Object.keys(data);
if(list.length > 0){
list.map((key,v)=>{
if( !reg.test(key )){
let now = Date.now();
let expires = data[`${key}__expires__`]||Date.now+1;
if (now >= expires ) {
this.remove(key);
};
};
return key;
});
};
}
}
总结:
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对本站的支持。
JS处理含Emoji或中文的字符串转数组乱码问题
2026-11-05 16:12:28
JS怎么使用展开运算符合并对象
2026-11-05 14:42:18
ES6+环境下判断JS对象为空的简洁写法
2026-11-05 12:12:23
怎么通过replacer函数自定义JS中JSON的格式化输出
2026-11-05 11:19:44
JS正则表达式基础:字面量与RegExp构造函数的区别及常用元字符
2026-11-05 11:16:58
