JS 如何检测到对象中有循环引用
更多描述 示例,如下数据为循环结构/循环引用
const user = { id: 10086, name: "山月" };
user._user = user;
追问:
- 由于
JSON.stringify
序列化对象时,将跳过不枚举的 key,因此此时可不考虑不可枚举的 key - 如果考虑不可枚举 key 与 Symbol 如何处理
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 683 (opens in a new tab)
Author 回答者: shfshanyue (opens in a new tab)
TODO
Author 回答者: yoyou (opens in a new tab)
const a = {
a:1,
c: 3
}
const b = {
a: a,
c: 3
}
a.b = b;
//JSON.stringify(a);
const keyMap = new Map();
keyMap.set(a, "1");
keyMap.set(b, "2");
function circle(target) {
const keys = Object.keys(target);
for(let i = 0; i < keys.length; i++) {
const key = keys[i];
const val = target[key];
if(keyMap.has(val)) {
return true
}else {
keyMap.set(val, key)
if(typeof val === 'object') {
circle(val)
}
}
}
return false;
}
console.log(circle(a))
Author 回答者: iotale (opens in a new tab)
const a = { a:1, c: 3 } const b = { a: a, c: 3 } a.b = b; //JSON.stringify(a); const keyMap = new Map(); keyMap.set(a, "1"); keyMap.set(b, "2"); function circle(target) { const keys = Object.keys(target); for(let i = 0; i < keys.length; i++) { const key = keys[i]; const val = target[key]; if(keyMap.has(val)) { return true }else { keyMap.set(val, key) if(typeof val === 'object') { circle(val) } } } return false; } console.log(circle(a))
可以将 Object.keys()
替换为 Reflect.ownKeys()
Author 回答者: haotie1990 (opens in a new tab)
function isCircularReference(value) {
const isObject = (value) =>
Object.prototype.toString.call(value) === "[object Object]";
const memory = new WeakMap();
let isCycled = false;
const traverse = function (value) {
if (isObject(value)) {
if (memory.has(value)) {
isCycled = true;
return;
}
memory.set(value, true);
const keys = Object.keys(value);
for (const key of keys) {
traverse(value[key]);
}
}
};
traverse(value);
return isCycled;
}
Author 回答者: haotie1990 (opens in a new tab)
function isCircularReference(value) { const isObject = (value) => Object.prototype.toString.call(value) === "[object Object]"; const memory = new WeakMap(); let isCycled = false; const traverse = function (value) { if (isObject(value)) { if (memory.has(value)) { isCycled = true; return; } memory.set(value, true); const keys = Object.keys(value); for (const key of keys) { traverse(value[key]); } } }; traverse(value); return isCycled; }
// isObject改为isPrimitive
const isPrimitive = (value) =>
/Number|Boolean|String|Undefined|Null|Symbol/.test(
Object.prototype.toString.call(value),
);
Author 回答者: heretic-G (opens in a new tab)
希望不可枚举和Symbol 可以Reflect.ownKeys(obj).map(curr => obj[curr]) 获取全部的key对应的values Object上面也有 不过是分开的 两个API
function checkObj(obj, set = new Set()) {
if ((typeof obj === "object" && obj !== null) || Array.isArray(obj)) {
if (set.has(obj)) {
return true;
} else {
set.add(obj);
}
return Object.values(obj).some((curr) => {
return checkObj(curr, set);
});
}
return false;
}
Author 回答者: Hishengs (opens in a new tab)
function isCircular(obj) {
try {
JSON.stringify(obj);
} catch (e) {
return e.message.includes("Converting circular structure to JSON");
}
return false;
}