Moo-Resig-Objs-My-Moa (fixed) (v31)

Revision 31 of this benchmark created by Pencroff on


Description

Comparing Mootools, John Resig, Objs & My.js class systems on class instantiation. Restore functionality and change klass.js to objs lib. Tests from first three revisions were merged to one big test. See result by test name.

Links: http://mootools.net/ http://ejohn.org/blog/simple-javascript-inheritance/ https://github.com/tekool/objs http://jiem.github.io/my-class/

Preparation HTML

<script src="https://ajax.googleapis.com/ajax/libs/mootools/1.3/mootools-yui-compressed.js"></script>

Setup

(function(){
      var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
      // The base Class implementation (does nothing)
      this.JRClass = function(){};
    
      // Create a new Class that inherits from this class
      JRClass.extend = function(prop) {
        var _super = this.prototype;
    
        // Instantiate a base class (but only create the instance,
        // don't run the init constructor)
        initializing = true;
        var prototype = new this();
        initializing = false;
    
        // Copy the properties over onto the new prototype
        for (var name in prop) {
          // Check if we're overwriting an existing function
          prototype[name] = typeof prop[name] == "function" &&
            typeof _super[name] == "function" && fnTest.test(prop[name]) ?
            (function(name, fn){
              return function() {
                var tmp = this._super;
    
                // Add a new ._super() method that is the same method
                // but on the super-class
                this._super = _super[name];
    
                // The method only need to be bound temporarily, so we
                // remove it when we're done executing
                var ret = fn.apply(this, arguments);
                this._super = tmp;
    
                return ret;
              };
            })(name, prop[name]) :
            prop[name];
        }
    
        // The dummy class constructor
        function JRClass() {
          // All construction is actually done in the init method
          if ( !initializing && this.init )
            this.init.apply(this, arguments);
        }
    
        // Populate our constructed prototype object
        JRClass.prototype = prototype;
    
        // Enforce the constructor to be what we expect
        JRClass.constructor = JRClass;
    
        // And make this class extendable
        JRClass.extend = arguments.callee;
    
        return JRClass;
      };
    })();
    
    var Objs;new function(){Objs=function(o,u,s){var r,p=typeof u,t,q,n;
    if(typeof o!=d){throw Error(j+o)}if(p==d){if(!b[u]){throw Error(g+u)}
    u=b[u]}else{if(p=="object"){s=u;u=null}}if(!u&&!s&&b[o]){return b[o]}
    r=b[o]=function(){if(!r[f]){if(r[i]){r[i][m]=1;r[i].call(this);
    delete r[i][m]}if(!r[m]&&r[k][a]){r[k][a].apply(this,arguments)}}};
    if(u){u[f]=1;r[k]=new u();delete u[f];r[i]=u;r[l]=u[k]}if(s){n=h.slice(0);
    for(t in s){if(s.hasOwnProperty(t)){n.push(t)}}for(q=0;q<n.length;q++)
    {t=n[q];r[k][t]=s[t]}}return r};var d="string",l="$super",e="class",i=l+e,
    k="prototype",a="initialize",c="$Objs$",m=c+"c",f=c+"e",g="Unexistent super"
    +e+": ",j="Invalid "+e+"path: ",b={},h=["toString","valueOf","toLocaleString"]};
    
    /*globals define:true, window:true, module:true*/(function(){var a={};typeof define!="undefined"?define([],function(){return a}):typeof window!="undefined"?window.my=a:module.exports=a,a.Class=function(){var a=arguments.length,d=arguments[a-1],e=a>1?arguments[0]:null,f=a>2,g,h;d.constructor===Object?g=function(){}:(g=d.constructor,delete d.constructor),e&&(h=function(){},h.prototype=e.prototype,g.prototype=new h,g.prototype.constructor=g,g.Super=e,c(g,e,!1));if(f)for(var i=1;i<a-1;i++)c(g.prototype,arguments[i].prototype,!1);return b(g,d),g};var b=a.extendClass=function(a,b,d){b.STATIC&&(c(a,b.STATIC,d),delete b.STATIC),c(a.prototype,b,d)},c=function(a,b,c){var d;if(c===!1)for(d in b)d in a||(a[d]=b[d]);else{for(d in b)a[d]=b[d];b.toString!==Object.prototype.toString&&(a.toString=b.toString)}}})();
    
    // Moa.JS
    !function(){Object.create||(Object.create=function(){function e(){}return function(t){if(1!==arguments.length)throw new Error("Object.create implementation only accepts one parameter.");e.prototype=t;return new e}}());var e,t="function",r="object",n="undefined",o={},i=function(e,t){var r;for(r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e},a=function(e,t){var r="Wrong parameters in "+e;t&&(r="Wrong parameter "+t+" in "+e);return new Error(r,"Moa")},c=function(e){return new Error("Type "+e+" not found","Moa")},f=function(t,r,n){var o,a=n.$ctor,c={};a!==e?delete n.$ctor:a=function(){};delete n.$extend;if(r!==e){o=r.$basetype;n=i(Object.create(r.$ctor.prototype),n)}n.getType=function(){return t};i(c,n);a.prototype=n;a.prototype.constructor=a;c.$ctor=a;return{$type:t,$basetype:o,$ctor:a,$base:c}},u={define:function(n,i){var u,p,d,s=arguments.length;switch(s){case 1:u=o[n];if(!u)throw c(n);break;case 2:switch(typeof i){case t:p=i().$extend;if(p!==e){d=o[p];if(d===e)throw c(p);u=f(n,d,i(d.$base))}else u=f(n,e,i(e));break;case r:if(null===i){delete o[n];return e}p=i.$extend;if(p!==e){d=o[p];if(d===e)throw c(p)}u=f(n,d,i);break;default:throw a("define","definition")}o[n]=u;break;default:throw a("define")}return u.$ctor}};typeof define!==n?define("Moa",[],function(){return u}):typeof window!==n?window.Moa=u:module.exports=u}();
    
    
    MooPerson = new Class({
      initialize: function(name) {
        this.name = name;
      },
      setAddress: function(country, city, street) {
        this.country = country;
        this.city = city;
        this.street = street;
      },
      sayHello: function() {
        console.log('I am ' + this.name + '. My address is ' +
            this.country + ', ' + this.city + ', ' + this.street + '.');
      }
    });
    MooFrenchGuy = new Class({
      Extends: MooPerson,
      initialize: function(name) {
        this.parent(name);
      },
      setAddress: function(city, street) {
        this.parent('France', city, street);
      }
    });
    MooParisLover = new Class({
      Extends: MooFrenchGuy,
      initialize: function(name) {
        this.parent(name);
      },
      setAddress: function(street) {
        this.parent('Paris', street);
      }
    }); 
    
    
    JRPerson = JRClass.extend({
      init: function(name){
        this.name = name;
      },
      setAddress: function(country, city, street) {
        this.country = country;
        this.city = city;
        this.street = street;
      },
      sayHello: function() {
        console.log('I am ' + this.name + '. My address is ' +
            this.country + ', ' + this.city + ', ' + this.street + '.');
      }
    });
    JRFrenchGuy = JRPerson.extend({
      init: function(name) {
        this._super(name);
      },
      setAddress: function(city, street) {
        this._super('France', city, street);
      }
    });
    JRParisLover = JRFrenchGuy.extend({
      init: function(name) {
        this._super(name);
      },
      setAddress: function(street) {
        this._super('Paris', street);
      }
    });
    
    ObjPerson = Objs("ObjPerson", {
        initialize: function(name) {
                this.name = name;
        },
        setAddress: function(country, city, street) {
          this.country = country;
          this.city = city;
          this.street = street;
        },
        sayHello: function() {
          console.log('I am ' + this.name + '. My address is ' +
              this.country + ', ' + this.city + ', ' + this.street + '.');
        }
    });
    ObjFrenchGuy = Objs("ObjFrenchGuy", "ObjPerson", {
      initialize: function(name) {
        ObjFrenchGuy.$super.initialize.call(this, name);
      },
      setAddress: function(city, street) {
        ObjFrenchGuy.$super.setAddress.call(this, 'France', city, street);
      }
    });
    ObjParisLover = Objs("ObjParisLover", "ObjFrenchGuy", {
      initialize: function(name) {
        ObjParisLover.$super.initialize.call(this, name);
      },
      setAddress: function(city, street) {
        ObjParisLover.$super.setAddress.call(this, 'France', city, street);
      }
    });
    
    MyPerson = my.Class({
        constructor: function(name) {
          this.name = name;
        },
        setAddress: function(country, city, street) {
          this.country = country;
          this.city = city;
          this.street = street;
        },
        sayHello: function() {
          console.log('I am ' + this.name + '. My address is ' +
              this.country + ', ' + this.city + ', ' + this.street + '.');
        }
      });
    MyFrenchGuy = my.Class(MyPerson, {
        constructor: function(name) {
          MyFrenchGuy.Super.call(this, name);
        },
        setAddress: function(city, street) {
          MyFrenchGuy.Super.prototype.setAddress.call(this, 'France', city, street);
        }
      });
    MyParisLover = my.Class(MyFrenchGuy, {
        constructor: function(name) {
          MyParisLover.Super.call(this, name);
        },
        setAddress: function(street) {
          MyParisLover.Super.prototype.setAddress.call(this, 'Paris', street);
        }
      });
    
    MoaPerson = Moa.define('MoaPerson', {
        $construct: function(name) {
          this.name = name;
        },
        setAddress: function(country, city, street) {
          this.country = country;
          this.city = city;
          this.street = street;
        },
        sayHello: function() {
          console.log('I am ' + this.name + '. My address is ' +
              this.country + ', ' + this.city + ', ' + this.street + '.');
        }
      });
    MoaFrenchGuy = Moa.define('MoaFrenchGuy', function($base){
    return {
        $extend: 'MoaPerson',
        $construct: function(name) {
          $base.$ctor.call(this, name);
        },
        setAddress: function(city, street) {
          $base.setAddress.call(this, 'France', city, street);
        }
      };
    });
    MoaParisLover = Moa.define('MyParisLover', function($base){
    return {
        $extend: 'MoaFrenchGuy',
        $construct: function(name) {
          $base.$ctor.call(this, name);
        },
        setAddress: function(street) {
          $base.setAddress.call(this, 'Paris', street);
        }
      };
    });
    
    var mooJohn = new MooParisLover('Carla Bruni');
    var jrJohn = new JRParisLover('Carla Bruni');
    var objJohn = new ObjParisLover('Carla Bruni');
    var myJohn = new MyParisLover('Carla Bruni');
    var moaJohn = new MoaParisLover('Carla Bruni');

Test runner

Ready to run.

Testing in
TestOps/sec
MooPerson instantiation
new MooPerson('John Doe');
ready
JRPerson instantiation
new JRPerson('John Doe');
ready
ObjPerson instantiation
new ObjPerson('John Doe');
ready
MyPerson instantiation
new MyPerson('John Doe');
ready
MoaPerson instantiation
new MoaPerson('John Doe');
 
ready
MooParisLover
new MooParisLover('Carla Bruni');
ready
JRParisLover
new JRParisLover('Carla Bruni');
ready
ObjParisLover
new ObjParisLover('Carla Bruni');
ready
MyParisLover
new MyParisLover('Carla Bruni');
ready
MoaParisLover
new MoaParisLover('Carla Bruni');
ready
Moo
mooJohn.setAddress('Matignon');
ready
John Resig
jrJohn.setAddress('Matignon');
ready
Objs
objJohn.setAddress('Matignon');
ready
My.js
myJohn.setAddress('Matignon');
ready
Moa.js
moaJohn.setAddress('Matignon');
ready

Revisions

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