判斷循環引用的方式主要有兩種:
- 可以使用 JSON.stringify() 方法將對象轉爲字符串,在轉化過程中,JSON.stringify() 方法會檢測對象中是否存在循環引用。如果存在循環引用,則轉化會出現異常,捕獲到異常後即可判斷出對象中存在循環引用。
let obj1 = {
name: 'Tom'
};
let obj2 = {
name: 'Jerry',
friend: obj1
}
obj1.friend = obj2;
let hasCircularReference = false;
try {
JSON.stringify(obj1);
} catch (e) {
hasCircularReference = true;
}
console.log(hasCircularReference); // 輸出 true
- 通過設置一個 Set 數據結構來記錄已經遍歷的對象,當遍歷到已經在 Set 中存在的對象時,說明出現了循環引用。需要注意的是,當遇到子對象時需要遞歸遍歷,並將已經遍歷過的對象記錄在 Set 中。
function hasCircularReferences(obj, set = new Set()) {
if (obj === null || typeof obj !== 'object') {
return false;
}
if (set.has(obj)) {
return true;
}
set.add(obj);
for (let key in obj) {
if (hasCircularReferences(obj[key], set)) {
return true;
}
}
return false;
}
let obj1 = {};
let obj2 = {};
obj1.friend = obj2;
obj2.friend = obj1;
console.log(hasCircularReferences(obj1)); // 輸出 true
不同的應用場景需要選擇不同的判斷方式。如果需要直接將對象轉爲字符串,以滿足某些需要字符串作爲參數的 API,第一種方式是一個不錯的選擇。如果需要進行更加靈活、嚴謹的操作,例如從對象中提取相關屬性,重建出一個不帶循環引用的新對象,使用第二種方式就比較方便。