JS面试手写:localStorage

182 阅读2分钟

localStorage的容量大家都知道是5M,但如下问题还是可以帮助我们进一步深入了解:

如何证明LocalStorage的容量大小是5M呢?

如何求得LocalStorage已使用的容量呢?

剩余容量又是多少呢?

如果超出5M的数据,接下来该如何存储呢?

证明总容量为5M:

我们以10KB一个单位,也就是10240B1024B就是10240个字节的大小,我们不断往localStorage中累加存入10KB,等到超出最大存储时,会报错,那个时候统计出所有累积的大小,就是总存储量了!

注意:计算前需要先清空LocalStorage

let str = ''
let temp = ''
// 先做一个 10KB 的字符串
while (str.length !== 10240) {
  str += '0123456789'
}
// 先清空localStorage
localStorage.clear()
const computedTotal = () => {
  return new Promise((resolve) => {
    // 不断往 LocalStorage 中累积存储 10KB
    const timer = setInterval(() => {
      try {
        localStorage.setItem('temp', temp)
      } catch {
        // 报错说明超出最大存储
        resolve(temp.length / 1024 )
        clearInterval(timer)
        // 统计完记得清空
        localStorage.clear()
      }
      temp += str
    }, 0)
  })
}
(async () => {
  const total = await computedTotal()
  console.log(`最大容量${total}KB`)
})()

求得LocalStorage已使用的容量:

计算已使用容量,我们只需要遍历localStorage(localStorage和sessionStorage都是可以直接拿到的对象)身上的存储属性,并计算每一个的length,累加起来就是已使用的容量了

const computedUse = () => {
  let cache = 0
  for(let key in localStorage) {
    if (localStorage.hasOwnProperty(key)) {
      cache += localStorage.getItem(key).length
    }
  }
  return (cache / 1024).toFixed(2)
}
(() => {
  const useCache = computedUse()
  console.log(`已用${useCache}KB`)
})()

求得LocalStorage的剩余容量

我们已经计算出总容量和已使用容量,那么剩余可用容量 = 总容量 - 已使用容量

const computedsurplus = (total, use) => {
  return total - use
}
(async () => {
  const total = await computedTotal()
  let o = '0123456789'
  for(let i = 0 ; i < 1000; i++) {
    o += '0123456789'
  }
  localStorage.setItem('o', o)
  const useCache = computedUse()
  console.log(`剩余可用容量${computedsurplus(total, useCache)}KB`)
})()

如果超出5M的数据,接下来该如何存储呢?

正常情况下,可能不会存储5M的字符串,但是也不能保证浏览器日积月累的情况下,恰巧用户也没清理过缓存,那么当最后容量接近5M的时候,我们再存储一个字符串进去的时候会发生错误,发生错误的字符串是存了一半?还是压根就没存呢?答案是---没存

那么超过了5M,接下来该怎么办呢?

  1. 当到写入localStorage的时候超出5M报错了,就清空localStorage:
(function(){
  var safeLocalStorage = function(key, value) {
    try{
      localStorage.setItem(key,value);
    }catch(oException){
      if(oException.name == 'QuotaExceededError'){
          console.log('已经超出本地存储限定大小!');
          // 可进行超出限定大小之后的操作,如下面可以先清除记录,再次保存
          localStorage.clear();
          localStorage.setItem(key,value);
      }
    }
  }
  this.safeLocalStorage = safeLocalStorage;
})();
  1. localStorage最大容量5M的意思是每一个域名下的localStorage容量是5M,假如现在a.com域名下localstorage存不下了,我们可以使用iframe创建b.com域框架(子页面)用于存储a.com剩下的数据。然后使用postMessage读写数据。

  2. 使用IndexedDB