如何判斷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值,通過處理之後,變成了循環引用的標識;

內容就這麼多,有錯誤但願大佬能夠多多指點,交流才能進步!對象

相關文章
相關標籤/搜索