Different ways of native inheritance

JavaScript performance comparison

Revision 7 of this test case created

Preparation code

<script>
   var augment = (function (bind, call) {
    "use strict";

    var bindable = Function.bindable = bind.bind(bind);
    var callable = Function.callable = bindable(call);

    var arrayFrom = Array.from = callable(Array.prototype.slice);
    var ownPropertyOf = Object.ownPropertyOf = callable(Object.hasOwnProperty);

    //Object.defineProperty(Function.prototype, "augment", augmentDescriptor);
    Object.defineProperty(Object.prototype, "augment", { value: augment });

    return callable(augment);

    function augment(body) {
        var base = typeof this === "function" ? this.prototype : this;
        var prototype = Object.create(base);
        body.apply(prototype, arrayFrom(arguments, 1).concat(base));
        if (!ownPropertyOf(prototype, "constructor")) return prototype;
        var constructor = prototype.constructor;
        constructor.prototype = prototype;
        return constructor;
    }
}(Function.bind, Function.call));


function extend() {
    var len = arguments.length;
    var parent = (len > 1) ? arguments[0] : Function.constructor;
    var body = arguments[len - 1];
    body.prototype = parent.prototype;

    var t = function (){
        if (this.init)
            this.init.apply(this, arguments);
    };
    t.prototype = new body(parent.prototype);
    return t;
}
</script>
<script>
Benchmark.prototype.setup = function() {
    function A1 () {
      this.pro1 = 'pro1 ';
      this.method1 = function(){ return this.pro1; };
      this.setpro = function(){ this.pro2='edited'; };
    }
   
    function B1() {
      this.pro2 = 'pro2 ';
      this.method2 = function(){return this.pro1 + this.pro2;};
    }
    B1.prototype = new A1();
   
    function C1() {
      this.pro3 = 'pro3 ';
      this.method3 = function(){return this.pro1 + this.pro2 + this.pro3 + this.method1() + this.method2();};
    }
    C1.prototype = new B1();
   
   
   
   
    function A2 () {
      this.pro1 = 'pro1 ';
      this.method1 = function(){ return this.pro1; };
      this.setpro = function(){ this.pro2='edited'; };
    }
   
    function B2() {
      this.pro2 = 'pro2 ';
      this.method2 = function(){return this.pro1 + this.pro2;};
      A2.apply(this, arguments);
    }
   
    function C2() {
      this.pro3 = 'pro3 ';
      this.method3 = function(){return this.pro1 + this.pro2 + this.pro3 + this.method1() + this.method2();};
      B2.apply(this, arguments);
    }
   
   
    function A3(){}
    A3.prototype.pro1 = 'pro1 ';
    A3.prototype.method1 = function(){ return this.pro1; };
    A3.prototype.setpro = function(){ this.pro2='edited'; };
   
    function B3(){}
    B3.prototype.pro2 = 'pro2 ';
    B3.prototype.method2 = function(){return this.pro1 + this.pro2;};
   
    for (i in A3.prototype)
        B3.prototype[i] = A3.prototype[i]
   
    function C3(){}
    C3.prototype.pro3 = 'pro3 ';
    C3.prototype.method3 = function(){return this.pro1 + this.pro2 + this.pro3 + this.method1() + this.method2();};
   
    for (i in B3.prototype)
        C3.prototype[i] = B3.prototype[i];
   
   
   
    function A4() {
      return {
        pro1: 'pro1 ',
        method1: function(){ return this.pro1; },
        setpro: function(){ this.pro2='edited'; }
      };
    }
    function B4() {
      var obj = A4();
      obj.pro2 = 'pro2 ';
      obj.method2 = function(){return this.pro1 + this.pro2;};
      return obj;
    }
    function C4() {
      var obj = B4();
      obj.pro3 = 'pro3 ';
      obj.method3 = function(){return this.pro1 + this.pro2 + this.pro3 + this.method1() + this.method2();};
      return obj;
    }
   
   
   
    var A5 = {
      pro1: 'pro1 ',
      method1: function(){ return this.pro1; },
      setpro: function(){ this.pro2='edited'; }
    };
   
    var B5 = Object.create(A5);
    B5.pro2 = 'pro2 ';
    B5.method2 = function(){return this.pro1 + this.pro2;};
   
    var C5 = Object.create(B5);
    C5.pro3 = 'pro3 ';
    C5.method3 = function(){return this.pro1 + this.pro2 + this.pro3 + this.method1() + this.method2();};
   
   
   
   
    function A6() {
      return {
        pro1: 'pro1 ',
        method1: function(){ return this.pro1; },
        setpro: function(){ this.pro2='edited'; }
      };
    }
    function B6() {
      var obj = {};
      obj.pro2 = 'pro2 ';
      obj.method2 = function(){return this.pro1 + this.pro2;};
      var a = A6();
      for (i in a)
        obj[i] = a[i];
      return obj;
    }
    function C6() {
      var obj = {};
      obj.pro3 = 'pro3 ';
      obj.method3 = function(){return this.pro1 + this.pro2 + this.pro3 + this.method1() + this.method2();};
      var b = B6();
      for (i in b)
        obj[i] = b[i];
      return obj;
    }
   
    var A7 = extend(function (base) {
        this.pro1 = 'pro1 ';
        this.method1 = function() {
            return this.pro1;
        };
        this.setpro = function(){ this.pro2='edited'; };
    });
    var B7 = extend(A7, function(base) {
        this.pro2 = 'pro2 ';
        this.method2 = function() {
            return this.pro1 + this.pro2;
        };
    });
    var C7 = extend(B7, function(base) {
        this.pro3 = 'pro3 ';
        this.method3 = function(){return this.pro1 + this.pro2 + this.pro3 + this.method1() + this.method2();};
    });
   
   
   
   
   
   
   
    var A8 = Object.augment(function () {
            this.pro1 = 'pro1 ';
            this.method1 = function() {
                return this.pro1;
            };
            this.setpro = function(){ this.pro2='edited'; };
            this.constructor = function() {};
        });
        var B8 = A8.augment(function() {
            this.pro2 = 'pro2 ';
            this.method2 = function() {
                return this.pro1 + this.pro2;
            };
            this.constructor = function() {};
        });
        var C8 = B8.augment(function() {
            this.pro3 = 'pro3 ';
            this.method3 = function(){return this.pro1 + this.pro2 + this.pro3 + this.method1() + this.method2();};
            this.constructor = function() {};
        });
};
</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
Pseudo-classical inheritance (through prototyping):
var inst = new C1()
inst.setpro();
inst.pro3 = 'changedout ';
inst.newm = function(){ this.pro1 = "# "; };
inst.newm();
inst.method3()
pending…
Function application or "constructor chaining"
var inst = new C2()
inst.setpro();
inst.pro3 = 'changedout ';
inst.newm = function(){ this.pro1 = "# "; };
inst.newm();
inst.method3()
pending…
Copying prototype iterating the Function.prototype
var inst = new C3()
inst.setpro();
inst.pro3 = 'changedout ';
inst.newm = function(){ this.pro1 = "# "; };
inst.newm();
inst.method3()
pending…
Parasitic inheritance or Power Constructors
var inst = C4();
inst.setpro();
inst.pro3 = 'changedout ';
inst.newm = function(){ this.pro1 = "# "; };
inst.newm();
inst.method3()
pending…
ECMAScript 5th Ed. Object.create method:
var inst = C5;
inst.setpro();
inst.pro3 = 'changedout ';
inst.newm = function(){ this.pro1 = "# "; };
inst.newm();
inst.method3()
pending…
Parasitic inheritance or Power Constructors (Iterating)
var inst = C6();
inst.setpro();
inst.pro3 = 'changedout ';
inst.newm = function(){ this.pro1 = "# "; };
inst.newm();
inst.method3()
pending…
inherit.js
var inst = new C7();
inst.setpro();
inst.pro3 = 'changedout ';
inst.newm = function(){ this.pro1 = "# "; };
inst.newm();
inst.method3()
pending…
augment.js
var inst = new C8();
inst.setpro();
inst.pro3 = 'changedout ';
inst.newm = function(){ this.pro1 = "# "; };
inst.newm();
inst.method3()
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