备案 控制台
学习
实践
活动
专区
工具
TVP
写文章
专栏首页 前端黑板报 JSON.stringify驯服循环引用的对象
2 0

海报分享

JSON.stringify驯服循环引用的对象

在写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){
    // 这里的key的判断条件,就是上面报错信息里的 property 'xxx' closes the circle,
    // 这里xxx是什么条件就是什么
    if(key == 'myself'){ 
        return 
    return value
})

如果嫌麻烦还有更简便的方法:

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;
}

运行如下:

JSON.stringify(circularReference, getCircularReplacer());
// {"otherData":123}

再推荐几个解决类似问题的库: