如何判断JS对象中是否存在循环引用

什么状况下会出现循环引用?

我我的的理解是,若是一个对象的值等于父级(祖父级,曾祖父级....),则说明是循环引用了。来看下面一个例子:ajax

用上面代码来解释我定义的循环引用:a.info的值是a,而a刚好是a.info的父级,因此这里就是循环引用了。数组

如何处理循环引用对象呢?

首先,循环引用对象原本没有什么问题,序列化的时候才会发生问题,好比调用JSON.stringify()对该类对象进行序列化,就会报错: Converting circular structure to JSON.,而序列化需求很常见,好比发起一个ajax请求提交一个对象就须要对对象进行序列化。bash

针对上面这样的问题,能够经过JSON扩展包的var c = JSON.decycle(a)var a = JSON.retrocycle(c)来处理。这里就不作过多的解释了。函数

重点来了

手动写一个方法来判断对象是否存在循环引用,来看下边一段代码:测试

function cycle(obj, parent) {
    //表示调用的父级数组
    var parentArr = parent || [obj];
    for (var i in obj) {
        if (typeof obj[i] === "object") {
            //判断是否有循环引用
            parentArr.forEach((pObj) => {
                if (pObj === obj[i]) {
                    obj[i] = "[cycle]"
                }
            });
            cycle(obj[i], [...parentArr, obj[i]])
        }
    }
    return obj;
}
复制代码

上面函数中,parentArr为取值的全部父级的一个集合;ui

循环对象,若是对象是一个object类型的,先循环数组parentArr,判断该值是不是parentArr中的引用,若是是,则存在循环引用,并把循环引用值设置成特殊标识"[cycle]",接着再进行递归调用,而且把对应取值链上的父级集合传递下去。spa

测试:code

var a = {
    b:{
        c:{}
    }
};

a.b.c.d = a;

console.log(cycle(a));
复制代码

结果以下: cdn

能够看到, a.b.c.d本来是一个循环引用的 a值,通过处理之后,变成了循环引用的标识;

内容就这么多,有错误但愿大佬能够多多指点,交流才能进步!对象

相关文章
相关标签/搜索