Given the ideas from the comments, I came up with this feature. It crosses the passed object (above the arrays and the object) and returns an array of paths pointing to circular links.
const getCycles = object => {
if (!object) {
return;
}
const traversedProps = new Set();
const cycles = [];
const traverse = function (currentObj, path) {
if (traversedProps.has(currentObj)) {
cycles.push(path);
return;
}
traversedProps.add(currentObj);
for (let key in currentObj) {
const value = currentObj[key];
if (currentObj.hasOwnProperty(key) && value) {
if (value.constructor === Object) {
let parentIsArray = currentObj.constructor === Array;
traverse(value, parentIsArray ? `${path}[${key}]` : `${path}.${key}`);
} else if (value.constructor === Array) {
for (let i = 0; i < value.length; i += 1) {
traverse(value[i], `${path}.${key}[${i}]`);
}
}
}
}
}
traverse(object, 'root');
return cycles;
};
Run codeHide resultThen you can check it as follows:
const x = {};
x.cycle = x;
const objWithCycles = {
prop: {},
prop2: [1, 2, [{subArray: x}]]
};
objWithCycles.prop.self = objWithCycles;
console.log(getCycles(objWithCycles));
Run codeHide resultIt produces the following output, which is a list of loops in an object:
[ 'root.prop.self', 'root.prop2[2][0].subArray.cycle' ]
source
share