怎么判断循环引用?
判断循环引用的方式主要有两种:
- 可以使用 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,第一种方式是一个不错的选择。如果需要进行更加灵活、严谨的操作,例如从对象中提取相关属性,重建出一个不带循环引用的新对象,使用第二种方式就比较方便。
forever young