You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
set (key, value) {
window.localStorage.setItem(prefix + key,JSON.stringify(value))
},
get (key) {
const v = window.localStorage.getItem(prefix + key)
return v ? JSON.parse(v) : v
}
背景
mgm库的Storage组件对localStorage的存取方法没有对数据做异常处理导致报错:
报错场景:
解决思路
如何处理localStorage
localStorage的键值对总是以字符串的形式存储。对于不是string类型的值,会自动执行toString()方法。然而,对于对象或数组而言,这个转换会丢失它原本的类型信息,导致值在取出的时候不能变为原来的格式。举例:
【例1】
localStorage.setItem('a', [1, 2, 3])
结果:localStorage的键值对依次是‘a'、'1,2,3'
【例2】
localStorage.setItem('a', {a: 1})
结果:ocalStorage的键值对依次是‘a'、'[object, object]'
所以,为了避免在数据转换过程中类型丢失,当我们要存入对象,数组的时候,要以某种编码方式把值做处理,转化为字符串再存进localStorage。这里用到的是JSON数据交换格式。值在存入localStorage前用JSON.stringify方法转化为符合JSON格式的值,从localStorage取出后用JSON.parse方法解析为原来的值。
关于JSON
JSON具有以下形式:
MDN上关于循环引用的对象不可序列化的限制是错的,实际验证了并没有(一开始没有验证,差点信了,还是要多动手试试)。stringify方法内部已经把这个循环引用给过滤了。举例:
【例3】
结果:
”{“a”:{“b”:{“c”:1}},”c”:1}”
需要注意的是,对于symbol类型值和undefined,序列化的结果是undefined。但是undefined值在解析的时候会报错,所以在把数据存入localStorage的时候把undefined值过滤掉,避免报错。
关于‘undefined'的序列化处理
JSON.stringify用法:
JSON.stringify(value[, replacer [, space]])
第二个参数是一个函数,可以在序列化过程中处理被序列化的值的属性。一开始我是想着用这个replacer函数j将’undefined’转换为undefined,这样子序列化的时候自然会把undefined忽略掉。
这也是一开始跟雅堂有争议的地方,‘undefined’这个字符串是不是有意义的,需不需要在序列化的时候过滤掉。我考虑的是值在运行时候的不确定性产生的’undefined‘并非喜闻乐见(想了想,好像自己也很少碰见程序莫名其妙跑出个’undefined‘值),索性把它干掉。雅堂考虑的是从字符串本身出发,它是有意义的。想了想,干预过多并非好事,就像用户的行为由他本身解释,字符串本身也应该自己解释自己才对。而且,程序的值如果是只是单纯的读写的话,更不要随意的手动更改。
try catch
不符合JSON规范的值解析会报异常,但传进JSON方法的值是不能在编写代码时确定的,因为JavaScript是一门动态类型语言,变量只有在运行过程中才能确定值的类型。因此,在程序运行过程中JSON.parse方法很可能传入一个非JSON规范的值。所以对于这种可能发生的程序异常,需要使用异常处理机制来防止代码报错,提升程序的容错能力。这里程序的异常处理用到了try catch异常处理机制。序列化和解析数据的代码放在try代码块中,如果有异常数据导致方法报错的话,在catch内部便可以捕捉到程序异常,并打印出警告。
关于console
console对象有很多方法属性可以辅助开发的,我经常用console.log方法打印日志,以致于信息不区分轻重全部log,这样容易忽略掉一些值得注意的程序异常。这里是数据异常引发方法运行出错,应该用console.warn方法输出警告信息,提醒开发者报错。
最终代码
The text was updated successfully, but these errors were encountered: