点击上方蓝色字体,关注我们
最近使用 Vue 写后台管理系统,在做 Tab 组件的持久化时遇到一个问题:
localStorage.setItem('tabs',JSON.stringify(tabs))
上面代码报错:
看意思应该是产生了循环引用的结构,下面是不同浏览器对于这个类型错误报出错的形式:
TypeError: cyclic object value (Firefox)
TypeError: Converting circular structure to JSON (Chrome and Opera)
TypeError: Circular reference in value argument not supported (Edge)
举个例子?:
var circularReference = {otherData: 123};
circularReference.myself = circularReference;
此时到控制台里面运行一下:
JSON.stringify(circularReference);
// 报错信息如下
VM685:1 Uncaught TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
--- property 'myself' closes the circle
at JSON.stringify ()
at:1:6
可以看到和我上面说的 Vue 的例子是类似的。
那如何解决呢?
既然是由于循环引用导致的,那我们可以在发生循环引用的地方给切断。
那如何切断呢?
幸好 JSON.stringify 方法提供了便利,语法如下:
JSON.stringify(value[, replacer[, space]])
replacer 可以作为一个函数传入,且接受 key 和 value 作为入参,如下:
JSON.stringiify({},function(key,value){
// do sth
})
那解决方案就有啦:
JSON.stringify(circularReference,function(key,value){
if(key == 'myself'){ // 这里的key的判断条件,就是上面报错信息里的 property 'xxx' closes the circle,这里xxx是什么条件就是什么
return
}
return value
})
每次需要定位 key 值,如果嫌麻烦还有更简便的方法:
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
}
推荐几个解决类似问题的库: