How to detect circular references in JavaScript

Lance Pollard

For example:

$ node
> var x = {}
undefined
> x.x = x
{ x: [Circular] }

Wondering the sort of structures are they using to accomplish this, because it's not encoded directly into what I just did. It seems like they would do something like:

var graph = new Graph(object)
graph.detectCircularReferences()

And then it would get them, but not sure how that works. Hoping to learn how to implement that.

Antonio Narkevich

Taking into an account the ideas from the comments I came to this function. It traverses the passed object (over arrays and object) and returns an array of paths that point to the circular references.

// This function is going to return an array of paths
// that point to the cycles in the object
const getCycles = object => {
    if (!object) {
        return;
    }

    // Save traversed references here
    const traversedProps = new Set();
    const cycles = [];

    // Recursive function to go over objects/arrays
    const traverse = function (currentObj, path) {
        // If we saw a node it's a cycle, no need to travers it's entries
        if (traversedProps.has(currentObj)) {
            cycles.push(path);
            return;
        }

        traversedProps.add(currentObj);

        // Traversing the entries
        for (let key in currentObj) {
            const value = currentObj[key];
            // We don't want to care about the falsy values
            // Only objects and arrays can produce the cycles and they are truthy
            if (currentObj.hasOwnProperty(key) && value) {
                if (value.constructor === Object) {
                    // We'd like to save path as parent[0] in case when parent obj is an array
                    // and parent.prop in case it's an 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}]`);
                    }
                }

                // We don't care of any other values except Arrays and objects.
            }
        }
    }

    traverse(object, 'root');
    return cycles;
};

Then you can test it like this:

// Making some cycles.
const x = {};
x.cycle = x;
const objWithCycles = {
    prop: {},
    prop2: [1, 2, [{subArray: x}]]
};
objWithCycles.prop.self = objWithCycles;

console.log(getCycles(objWithCycles));

It produces the following output which is a list of cycles in the object:

[ 'root.prop.self', 'root.prop2[2][0].subArray.cycle' ]

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How does Python's Garbage Collector Detect Circular References?

How does Python's Garbage Collector Detect Circular References?

How do I remove all circular references from an object in JavaScript?

How to use @JsonIdentityInfo with circular references?

Javascript Deep Clone Object with Circular References

How to handle class object with circular references?

How do double closures break circular references?

How to detect mouseover an image (circular) in pygame

References and How They Work in JavaScript

Passing data with circular references to a javascript web worker on Chrome

How can i avoid circular references in type aliases

GSON: how to prevent StackOverflowError while keeping circular references?

How to deal with circular references in JPA and Hibernate with associative entity

How does Java Garbage Collection work with Circular References?

Value-equals and circular references: how to resolve infinite recursion?

How to avoid circular dependency while adding references to windows runtimecomponent?

How do Typescript templates work with circular references and inheritance?

Persisting circular references in Hibernate

Circular References in Java

Reason for circular references with classes?

Are "circular references" in JPA an antipattern?

Creating circular generic references

Circular references with vals in Kotlin

Circular model references

How to detect if JavaScript is disabled?

how to detect Browser with JavaScript?

How do I detect overlapping almost circular objects in MATLAB?

how I could detect this circular blob using imagemagick or another language?

detect circular reference in an object