isCircularObject vs isCircular vs isCircularES5

JavaScript performance comparison

Revision 11 of this test case created by Xotic750

Preparation code

<script src="//rghost.net/download/44912099/476adfd5820353ee828f1cc79bdfdc8ff41c9d70/utility3.min.js"></script>
<script>
Benchmark.prototype.setup = function() {
    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;
    }
   
    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…
$u.isCircular
$u.isCircular(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