Class Pattern Comparisons: Object Creation

JavaScript performance comparison

Test case created by Donald Atkinson

Info

This is a smaller test group for Class Pattern Comparison. For background, it is advisable to go to the full test page

Test Requirements and Considerations

In order to properly determine the performance statistics, all classes have been made as similarly as possible. This helps to validate the accuracy of the performance in proper comparison to like functionality.

Despite the rigidity of the requirements, there are some differences that cannot be accounted for. For instance, the prototype and constructor patterns cannot have private static methods. The prototype method cannot expose private data, though the other two can.

Class Characteristics

Except for the last case, which allows prototypes private member access, all classes in this test have 5 public methods, 2 class(static) methods, 2 public data members and 1 private data member.

The last case adds an additional public method in its constructor.

Additional Notes

Preparation code

<!-- Shim from es5-shim: Function.prototype.apply() -->
<script>(function(){var d=!1,b=Function.prototype.apply;try{d=isNaN.apply(null,{})}catch(e){}d||(Function.prototype.apply=function(c,a){return a?"object"!==typeof a||a instanceof Array||!("length"in a)?b.call(this,c,a):b.call(this,c,Array.from(a)):b.call(this,c)})})();</script>

<script>
var ProtoObject = function(cfg) {
    var dataPrivate = 0;
    this.dataPublic = 0;
};
ProtoObject.staticMethod = function(){
   return 0;
};
ProtoObject.staticMethod2 = function(){
   return 0;
};
ProtoObject.prototype = {
    dummy: 0,
    doSomething: function(value) {
        return value + 1;
    },
    runStaticMethod: function() {
        return ProtoObject.staticMethod();
    },
    dummyFn1: function() {
        return 0;
    },
    dummyFn2: function() {
        return 0;
    },
    dummyFn3: function() {
        return 0;
    },
    dummyFn3: function() {
        return 0;
    },
};

var ConstructedObject = function(cfg) {
    var dataPrivate = 0;

    this.dummy = 0;
    this.dataPublic = 0;

    this.doSomething = function(value) {
         return value + 1;
    };
    this.runStaticMethod = function() {
         return ConstructedObject.staticMethod();
    };
    this.dummyFn1 = function() {
        return 0;
    };
    this.dummyFn2 = function() {
        return 0;
    };
    this.dummyFn3 = function() {
        return 0;
    };
    this.dummyFn4 = function() {
        return 0;
    };
};
ConstructedObject.staticMethod = function(){
    return 0;
};
ConstructedObject.staticMethod2 = function(){
    return 0;
};

var HoistedConstructedObject = function(cfg) {
    var dataPrivate = 0;

    this.dummy = 0;
    this.dataPublic = 0;

    function doSomething(value) {
         return value + 1;
    }
    this.doSomething = doSomething;

    function runStaticMethod() {
         return ConstructedObject.staticMethod();
    }
    this.runStaticMethod = runStaticMethod;

    function dummy1() {
        return 0;
    }
    function dummy2() {
        return 0;
    }
    function dummy3() {
        return 0;
    }
    this.dummyFn1 = dummy1;
    this.dummyFn2 = dummy2;
    this.dummyFn3 = dummy3;
};
HoistedConstructedObject.staticMethod = function(){
    return 0;
};
HoistedConstructedObject.staticMethod2 = function(){
    return 0;
};


var ClassModuleObject1 = (function(Class) {
    function staticMethodPrivate() {
            return 0;
    }
    function exposedStaticMethod() {
            return 0;
    }

    Class.staticMethod = function() {
        return 0;
    };
    Class.exposedStaticMethod = exposedStaticMethod;
   
    Class.prototype.class = Class;
    Class.prototype.doSomething = function(value) {
        return value + 1;
    };
    Class.prototype.runStaticMethod1 = function() {
        return Class.staticMethod();
    };
    Class.prototype.runStaticMethod2 = function() {
        return Class.exposedStaticMethod();
    };
    Class.prototype.runPrivateStaticMethod = function() {
        return staticMethodPrivate();
    };

    Class.prototype.getPrivateData = function() {
      // Placeholder for performance matching
      return 0
    }

    Class.create = function(cfg) {
        var dataPrivate = 50;

        this.dataPublic = 0;
    };

// Return the Actual Class
    return Class;
}(function(cfg){
    return this.class.create.apply(this, arguments);
}));

var ClassModuleObject2 = (function(Class) {
    function staticMethodPrivate() {
            return 0;
    }
    function exposedStaticMethod() {
            return 0;
    }

    Class.staticMethod = function() {
        return 0;
    };
    Class.exposedStaticMethod = exposedStaticMethod;
   
    Class.prototype.class = Class;
    Class.prototype.doSomething = function(value) {
        return value + 1;
    };
    Class.prototype.runStaticMethod1 = function() {
        return Class.staticMethod();
    };
    Class.prototype.runStaticMethod2 = function() {
        return Class.exposedStaticMethod();
    };
    Class.prototype.runPrivateStaticMethod = function() {
        return staticMethodPrivate();
    };

    Class.prototype.getPrivateData = function() {
      // Placeholder for later testing
        return 0;
    }

    Class.create = function(cfg) {
        var dataPrivate = 0;

        if (this instanceof Class) {
            this.dataPublic = 0;
        }
        else {
            return new Class(cfg);
        }
    };

// Return the Actual Class
    return Class;
}(function(cfg){
    return this.class.create.apply(this, arguments);
}));

var ClassModuleObject3 = (function(Class) {
    var syncPrivateAccess = false;

    function staticMethodPrivate() {
            return 0;
    }
    function exposedStaticMethod() {
            return 0;
    }

    Class.staticMethod = function() {
        return 0;
    };
    Class.exposedStaticMethod = exposedStaticMethod;
   
    Class.prototype.class = Class;
    Class.prototype.doSomething = function(value) {
        return value + 1;
    };
    Class.prototype.runStaticMethod1 = function() {
        return Class.staticMethod();
    };
    Class.prototype.runStaticMethod2 = function() {
        return Class.exposedStaticMethod();
    };
    Class.prototype.runPrivateStaticMethod = function() {
        return staticMethodPrivate();
    };

    Class.prototype.getPrivateData = function() {
        var result;
        syncPrivateAccess = true;
        result = this.read();
        syncPrivateAccess = false;
        return result;
    }

    Class.create = function(cfg) {
        var dataPrivate = 0;
        function read() {
            if (syncPrivateAccess) return dataPrivate;
        }

        if (this instanceof Class) {
            this.dataPublic = 0;
            this.read = read;
        }
        else {
            return new Class(cfg);
        }
    };

// Return the Actual Class
    return Class;
}(function(cfg){
    return this.class.create.apply(this, arguments);
}));
</script>

Preparation code output

Test runner

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

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Prototype new()
var obj = new ProtoObject();
pending…
Constructor new() [Non-Hoisted]
var obj = new ConstructedObject();
pending…
Constructor new() [Hoisted]
var obj = new HoistedConstructedObject();
pending…
Modular new()
var obj = new ClassModuleObject1();
pending…
Modular new() w/ Static Creation
var obj = new ClassModuleObject2();
pending…
Modular new() w/ Private Access and Static Creation
var obj = new ClassModuleObject3();
pending…
Static Creation
var obj = ClassModuleObject2.create();
pending…

You can edit these tests or add even more tests to this page by appending /edit to the URL.

Compare results of other browsers

0 comments

Add a comment