前言
由于项目中,我们会经常使用localStorage
去进行存储,可能会存token信息
、背景主题
、路由参数
……,接下来总结一下localStorage的拓展用法或者是面试官喜欢问的点
使用
下面列出一些常用的api供大家参考
localStorage.setItem(key,value)
新增数据
localStorage.getItem(key)
取数据
localStorage.removeItem(key)
移除数据
localStorage.clear()
清空数据
localStorage设置时效性
面试官:我们都知道
localStorage
必须我们手动去清除数据,那我们怎么设置时效性呢?
我们其实可以通过给localStorage
设置数据时,我们去添加一个时间戳,并且我们在getItem
的时候我们可以根据之前设置的时间戳,进行判断我们需不需要把这个数据清除或者其他操作
根据我们Date
实例对象上的getTime
方法(详情见mdn官方文档这里不详细说明)并且我们的时间是一个毫秒的单位,将getItem
的时间和setItem
相减判断
- 封装一下
setItem
时候的函数
const set = () => {
const now = new Date().getTime();
localStorage.setItem("key", JSON.stringify({ value: "data", time: now }));
}
- 封装一下
getItem
时候的函数
我们首先拿到key所对应的value值,并且去找到之前设置的一个时间,并且拿到此时的时间,和传入的时间做对比就可以啦,过期的话就直接把key删掉就可以,没过期的话,根据情况是否要更新时间全看自己了,注意:
时间传入的值是毫秒为单位的,若设置1000,则是有效期1秒
const get = (key, time) => {
const localData = localStorage.getItem(key);
if (!localData) return "";
const localDataObj = JSON.parse(localData);
const nowTime = new Date().getTime();
const localDataTime = localDataObj.time || nowTime;
if (nowTime - localDataObj.time > time) {
console.log("数据已过期");
// 删除
localStorage.removeItem(key);
return false;
} else {
if (!localDataObj.data) return "";
const data = JSON.parse(localDataObj.data);
return data;
}
};
set() //调用函数set
get(key,1000) // 此时的1000指的是1s喔
get(key,1000 * 60 )
若localStorage存在多个无效key怎么办
面试官:会不会有存在多少个无效key的情况呢?若是有的话我们怎么解决?或者说我们现在最多能让localStorage最多存储10个key,我们怎么根据我们最少使用的这么一个key把他删掉,在添加一个新的key呢?
我:……轮询去查看localStorage,并且设置个标志位count,每当我们
getItem
的时候我们count++,当数量到达十个的时候,我们遍历这10个key看他的一个count数量(回答到这的时候感觉回答的还是可以的只是自我感觉而已)面试官:那也有问题,如果我们第一天访问
key1
1次,我们第二天访问key1
100次,我们第三天访问key2
200次,key1
访问10次,那我们还是会把key1
删掉啊我:(面试官反应好快)啊这……那我们可以传一个时间戳进行判断呀
面试官:可以不用时间戳呢,还有其他办法
我:实在不会了……
其实此刻的面试官其实想问的是我们的LRU
算法,也就是最近最少使用算法(力扣:LRU算法)
我们可以利用javascript
的数据结构Map
,因为我们的Map插入是个有序的,并且我们的操作复杂度为O(1)
我们插入数据的时候,若有旧数据需要把旧数据保存再进行删除,重新set
一遍处于底部的位置,并且要判断是否超过你最大的一个容量,若超过容量的话把头部的数据删掉
访问的时候,我们也会把数据重新插入到底部,和插入数据其实原理是一样的
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.map = new Map();
}
get(key) {
if (this.map.has(key)) {
// get表示访问该值
// 所以在访问的同时,要将其调整位置,放置在最后
const temp = this.map.get(key);
// 先删除,再添加
this.map.delete(key);
this.map.set(key, temp);
// 返回访问的值
return temp;
} else {
// 不存在,返回-1
return -1;
}
}
put(key, value) {
// 要将其放在最后,所以若存在key,先删除
if (this.map.has(key)) this.map.delete(key);
// 设置key、value
this.map.set(key, value);
if (this.map.size > this.capacity) {
// 若超出范围,将map中头部的删除
// map.keys()返回一个迭代器
// 迭代器调用next()方法,返回包含迭代器返回的下一个值,在value中
this.map.delete(this.map.keys().next().value);
}
}
}
怎么测试localStorage大小
面试官:那我们怎么判断localStorage的大小呢?
我:(思考了一波)我们可以利用累加的方法……诶?(妈的好像有点不太对……本来想说一直累加数据直到我们不能累加为止)
面试官:……
面试官:其实就是我们一直加数据+我们的错误处理,直到localStorage不能添加为止
我:对对,我刚刚想的就是这个……
首先我们要先对localStorage有一些基本了解,这里就不细讲了
localStorage
存储的键和值始终采用UTF-16 DOMString格式
- 5M的单位就是字符串的长度,而不是字符数
localStorage
的键占不占空间??占空间
这个其实可以根据一个简单的例子来证明:
- 我们把 key和val各自设置长 2.5M的长度
- 此时我们把键值 +0.1
const charTxt = "a";
let count = (2.5 * 1024 * 1024);
let content = new Array(count).fill(charTxt).join("") + 0.1; //+0.1
const key = new Array(count).fill(charTxt).join("");
localStorage.clear();
try {
console.time("setItem")
localStorage.setItem(key, content);
console.timeEnd("setItem")
} catch (err) {
console.log("err", err);
}
下面为报错的详情
- 若我们此时把我们value -0.1,其实是可以运行的,小伙伴可以试一下!
这个方法其实就是测试localStorage大小的方法
结语
上面总结的问题也是最近春招被问得比较多的问题,也学习到蛮多东西的!
如果你觉得此文对你有一丁点的帮助,点个赞!