isCircularObject vs isCircular vs isCircularES5

JavaScript performance comparison

Revision 3 of this test case created by Xotic750

Preparation code

<script>
function isCircular(obj, arr) {
    "use strict";

    var type = typeof obj,
        propName,
        thisVal,
        iterArr,
        lastArr;

    if (type !== "object" && type !== "function") {
        return false;
    }

    if (Object.prototype.toString.call(arr) !== '[object Array]') {
        type = typeof arr; // jslint sake
        if (!(type === "undefined" || type === null)) {
            throw new TypeError("Expected attribute to be an array");
        }

        arr = [];
    }

    arr.push(obj);
    lastArr = arr.length - 1;

    for (propName in obj) {
        thisVal = obj[propName];
        type = typeof thisVal;

        if (type === "object" || type === "function") {
            for (iterArr = lastArr; iterArr >= 0; iterArr -= 1) {
                if (thisVal === arr[iterArr]) {
                    return true;
                }
            }

            if (isCircular(thisVal, arr)) {
                return true;
            }

        }
    }

    arr.pop(obj);
    return false;
}

function isCircularES5Hybrid1(obj, arr) {
    "use strict";

    var type = typeof obj,
        propName,
        keys,
        thisVal,
        iterKeys;


    if (type !== "object" && type !== "function") {
        return false;
    }

    if (!Array.isArray(arr)) {
        type = typeof arr; // jslint sake
        if (!(type === "undefined" || type === null)) {
            throw new TypeError("Expected attribute to be an array");
        }

        arr = [];
    }

    arr.push(obj);

    for (propName in obj) {
        thisVal = obj[propName];
        type = typeof thisVal;

        if (type === "object" || type === "function") {
            if (arr.indexOf(obj[propName]) >= 0) {
                return true;
            }

            if (isCircular(thisVal, arr)) {
                return true;
            }

        }
    }

    arr.pop(obj);
    return false;
}

function isCircularES5(obj, arr) {
    "use strict";

    var type = typeof obj,
        propName,
        keys,
        thisVal,
        iterKeys;


    if (type !== "object" && type !== "function") {
        return false;
    }

    if (!Array.isArray(arr)) {
        type = typeof arr; // jslint sake
        if (!(type === "undefined" || type === null)) {
            throw new TypeError("Expected attribute to be an array");
        }

        arr = [];
    }

    arr.push(obj);

    keys = Object.keys(obj);
    for (iterKeys = keys.length - 1; iterKeys >= 0; iterKeys -= 1) {
        propName = keys[iterKeys];
        thisVal = obj[keys[iterKeys]];
        type = typeof thisVal;

        if (type === "object" || type === "function") {
            if (arr.indexOf(obj[propName]) >= 0) {
                return true;
            }

            if (isCircular(thisVal, arr)) {
                return true;
            }

        }
    }

    arr.pop(obj);
    return false;
}

function isCircularObject(node, parents) {
    parents = parents || [];

    if (!node || typeof node != "object") {
        return false;
    }

    var keys = Object.keys(node), i, value;

    parents.push(node); // add self to current path
    for (i = keys.length-1; i >= 0; i--) {
        value = node[keys[i]];
        if (value && typeof value == "object") {
            if (parents.indexOf(value) >= 0) {
                // circularity detected!
                return true;
            }

            // check child nodes
            if (arguments.callee(value, parents)) {
                return true;
            }

        }
    }

    parents.pop(node);
    return false;
}
</script>
<script>
Benchmark.prototype.setup = function() {
    var testObject = Object;
};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
isCircularObject
isCircularObject(testObject);
pending…
isCircular
isCircular(testObject);
pending…
isCircularES5
isCircularES5(testObject);
pending…
isCircularES5Hybrid1
isCircularES5Hybrid1(testObject);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment