JS 如何检测到对象中有循环引用
更多描述 示例,如下数据为循环结构/循环引用
const user = { id: 10086, name: "山月" };
user._user = user;
追问:
- 由于
JSON.stringify
序列化对象时,将跳过不枚举的 key,因此此时可不考虑不可枚举的 key - 如果考虑不可枚举 key 与 Symbol 如何处理
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 683
Author 回答者: shfshanyue
TODO
Author 回答者: yoyou
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
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
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
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
希望不可枚举和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
function isCircular(obj) {
try {
JSON.stringify(obj);
} catch (e) {
return e.message.includes("Converting circular structure to JSON");
}
return false;
}
Author 回答者: cloudGrin
上面没有一个答案是对的啊,试试这个对象返回的都是true
const c = {}; const d = { e:c, f:c }
Author 回答者: cloudGrin
function hasCircularReference(obj, seenObjects = new Set()) {
if (typeof obj !== "object" || obj === null) {
return false;
}
if (seenObjects.has(obj)) {
return true;
}
seenObjects.add(obj);
for (let key in obj) {
if (hasCircularReference(obj[key], new Set([...seenObjects]))) {
return true;
}
}
return false;
}