JavaScript Object Oriented Libraries Benchmark

JavaScript performance comparison

Revision 11 of this test case created by André Cruz

Info

=== SUPER CALL ===

MooTools and Ext Core are removed because they add extra information into native classes. They slow down other libraries.

Ext Core OOP is fast, MooTools OOP is super slow!

TODO: - Add YUI

Preparation code

<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/jsface.js"></script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/jsface.js"></script>

<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/my.class.js"</script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/my.class.js"</script>

<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/jrclass.js"</script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/jrclass.js"</script>

<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/klass.js"></script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/klass.js"></script>

<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/classy.js"></script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/classy.js"></script>

<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/ptclass.js"</script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/lib/ptclass.js"</script>

<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/all.js"></script>
<script src="http://dl.dropbox.com/u/7677927/oop-benchmark/all.js"></script>

<script>
(function(){var a,b,c;(function(d){function j(a,b){if(a&&a.charAt(0)==="."&&b){b=b.split("/"),b=b.slice(0,b.length-1),a=b.concat(a.split("/"));var c,d;for(c=0;d=a[c];c++)if(d===".")a.splice(c,1),c-=1;else if(d==="..")if(c!==1||a[2]!==".."&&a[0]!=="..")c>0&&(a.splice(c-1,2),c-=2);else break;a=a.join("/")}return a}function k(a,b){return function(){return i.apply(d,g.call(arguments,0).concat([a,b]))}}function l(a){return function(b){return j(b,a)}}function m(a){return function(b){e[a]=b}}function n(a){if(f.hasOwnProperty(a)){var b=f[a];delete f[a],h.apply(d,b)}return e[a]}function o(a,b){var c,d,e=a.indexOf("!");return e!==-1?(c=j(a.slice(0,e),b),a=a.slice(e+1),d=n(c),d&&d.normalize?a=d.normalize(a,l(b)):a=j(a,b)):a=j(a,b),{f:c?c+"!"+a:a,n:a,p:d}}var e={},f={},g=[].slice,h,i;if(typeof c=="function")return;h=function(a,b,c,g){var h=[],i,j,l,p,q,r;g||(g=a);if(typeof c=="function"){!b.length&&c.length&&(b=["require","exports","module"]);for(p=0;p<b.length;p++){r=o(b[p],g),l=r.f;if(l==="require")h[p]=k(a);else if(l==="exports")h[p]=e[a]={},i=!0;else if(l==="module")j=h[p]={id:a,uri:"",exports:e[a]};else if(e.hasOwnProperty(l)||f.hasOwnProperty(l))h[p]=n(l);else if(r.p)r.p.load(r.n,k(g,!0),m(l),{}),h[p]=e[l];else throw a+" missing "+l}q=c.apply(e[a],h),a&&(j&&j.exports!==d?e[a]=j.exports:i||(e[a]=q))}else a&&(e[a]=c)},a=i=function(a,b,c,e){return typeof a=="string"?n(o(a,b).f):(a.splice||(b.splice?(a=b,b=arguments[2]):a=[]),e?h(d,a,b,c):setTimeout(function(){h(d,a,b,c)},15),i)},i.config=function(){return i},b||(b=i),c=function(a,b,d){b.splice||(d=b,b=[]),c.unordered?f[a]=[a,b,d]:h(a,b,d)},c.amd={jQuery:!0}})(),c("../vendor/almond/almond.js",function(){}),c("Utils/lang/kindOf",[],function(){function d(d){return d===null?"Null":d===c?"Undefined":a.exec(b.call(d))[1]}var a=/^\[object (.*)\]$/,b=Object.prototype.toString,c;return d}),c("Utils/lang/isKind",["./kindOf"],function(a){function b(b,c){return a(b)===c}return b}),c("Utils/lang/isNumber",["./isKind"],function(a){function b(b){return a(b,"Number")}return b}),c("Utils/lang/isRegExp",["./isKind"],function(a){function b(b){return a(b,"RegExp")}return b}),c("Utils/lang/isString",["./isKind"],function(a){function b(b){return a(b,"String")}return b}),c("Utils/lang/isBoolean",["./isKind"],function(a){function b(b){return a(b,"Boolean")}return b}),c("common/isPrimitiveType",["Utils/lang/isNumber","Utils/lang/isRegExp","Utils/lang/isString","Utils/lang/isBoolean"],function(a,b,c,d){function e(e){return a(e)||c(e)||d(e)||b(e)||e==null}return e}),c("Utils/lang/isFunction",["./isKind"],function(a){function b(b){return a(b,"Function")}return b}),c("Utils/lang/isObject",["./isKind"],function(a){function b(b){return a(b,"Object")}return b}),c("Utils/lang/isArray",["./isKind"],function(a){var b=Array.isArray||function(b){return a(b,"Array")};return b}),c("Utils/lang/isDate",["./isKind"],function(a){function b(b){return a(b,"Date")}return b}),c("Utils/lang/isUndefined",[],function(){function b(b){return b===a}var a;return b}),c("Utils/object/hasOwn",[],function(){function a(a,b){return Object.prototype.hasOwnProperty.call(a,b)}return a}),c("Utils/object/mixIn",["./hasOwn"],function(a){function b(b,c){var d=1,e=arguments.length,f,g;while(g=arguments[d++])for(f in g)a(g,f)&&(b[f]=g[f]);return b}return b}),c("Utils/lang/createObject",["../object/mixIn"],function(a){function b(b,c){function d(){}return d.prototype=b,a(new d,c)}return b}),c("Utils/array/indexOf",[],function(){var a=Array.prototype.indexOf?function(a,b,c){return a.indexOf(b,c)}:function(a,b,c){c=c||0;var d=a.length>>>0,e=c<0?d+c:c;for(;e<d;e++)if(a[e]===b)return e;return-1};return a}),c("Utils/array/combine",["./indexOf"],function(a){function b(b,c){var d,e=c.length;for(d=0;d<e;d++)a(b,c[d])===-1&&b.push(c[d]);return b}return b}),c("Utils/array/contains",["./indexOf"],function(a){function b(b,c){return a(b,c)!==-1}return b}),c("common/mixIn",[],function(){function a(a,b){var c,d=arguments.length,e,f;for(c=1;c<d;c+=1){f=arguments[c];for(e in arguments[c])a[e]=f[e]}return a}return a}),c("Utils/array/append",[],function(){function a(a,b){return Array.prototype.push.apply(a,b),a}return a}),c("Utils/array/forEach",[],function(){var a=Array.prototype.forEach?function(a,b,c){a.forEach(b,c)}:function(a,b,c){for(var d=0,e=a.length>>>0;d<e;d++)d in a&&b.call(c,a[d],d,a)};return a}),c("Utils/array/filter",["./forEach"],function(a){var b=Array.prototype.filter?function(a,b,c){return a.filter(b,c)}:function(b,c,d){var e=[];return a(b,function(a,b,f){c.call(d,a,b,f)&&e.push(a)}),e};return b}),c("Utils/array/unique",["./indexOf","./filter"],function(a,b){function c(a){return b(a,d)}function d(b,c,d){return a(d,b,c+1)===-1}return c}),c("Utils/array/some",["require"],function(a){var b=Array.prototype.some?function(a,b,c){return a.some(b,c)}:function(a,b,c){var d=!1,e=a.length>>>0;while(e--)if(e in a&&b.call(c,a[e],e,a)){d=!0;break}return d};return b}),c("Utils/array/difference",["./unique","./filter","./some","./contains"],function(a,b,c,d){function e(e){var f=Array.prototype.slice.call(arguments,1),g=b(a(e),function(a){return!c(f,function(b){return d(b,a)})});return g}return e}),c("Utils/lang/bind",[],function(){function a(a,b){return Array.prototype.slice.call(a,b||0)}function b(b,c,d){var e=a(arguments,2);return function(){return b.apply(c,e.concat(a(arguments)))}}return b}),c("Utils/lang/isArguments",["./isKind"],function(a){var b=a(arguments,"Arguments")?function(b){return a(b,"Arguments")}:function(a){return!!a&&!!Object.prototype.hasOwnProperty.call(a,"callee")};return b}),c("Utils/lang/toArray",["./isArray","./isObject","./isArguments"],function(a,b,c){function e(e){var f;return e==null?f=[]:e&&e!==d&&(a(e)||c(e)||b(e)&&"length"in e)?f=Array.prototype.slice.call(e):f=[e],f}var d=this;return e}),c("Utils/array/insert",["./difference","../lang/toArray"],function(a,b){function c(c,d){var e=a(b(arguments).slice(1),c);return e.length&&Array.prototype.push.apply(c,e),c.length}return c}),c("Class",["./common/isPrimitiveType","Utils/lang/isFunction","Utils/lang/isObject","Utils/lang/isArray","Utils/lang/isDate","Utils/lang/isUndefined","Utils/lang/createObject","Utils/object/hasOwn","Utils/array/combine","Utils/array/contains","./common/mixIn","Utils/array/append","Utils/array/insert","Utils/lang/bind","Utils/lang/toArray"],function(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){function v(a){var b;return e(a)?[].concat(a):d(a)?l({},a):f(a)?(b=new Date,b.setTime(a.getTime()),b):a}function w(a){if(i(a.prototype,"$borrows")){var e,f,h,k,m=p(a.prototype.$borrows),o=m.length;for(o-=1;o>=0;o-=1){e=d(m[o])?(new q(l({},m[o]))).prototype:m[o].prototype;for(h in e)k=e[h],g(a.prototype[h])&&(a.prototype[h]=k,c(k)&&!k[s]&&!k[t]?(k["$prototype_"+a[s].id]=a.prototype,k.$name=h):b(k)||n(a[s].properties,k));for(f=e.$constructor[s].staticMethods.length-1;f>=0;f-=1)h=e.$constructor[s].staticMethods[f],g(a[h])&&(n(a[s].staticMethods,h),a[h]=e.$constructor[h],a[h]["$constructor_"+a[s].id]=a,a[h].$name=h);for(h in e.$constructor[s].staticProperties)k=e.$constructor[s].staticProperties[h],g(a[h])&&(a[s].staticProperties[h]=k,a[h]=v(k));j(a[s].binds,e.$constructor[s].binds)}delete a.prototype.$borrows}}function x(a,b){a=p(a);var c,d=a.length,e;for(d-=1;d>=0;d-=1){c=a[d];if(!k(b[s].interfaces,c)){for(e=c[t].constants.length-1;e>=0;e-=1)b[c[t].constants[e]]=c[c[t].constants[e]],b[s].staticProperties[c[t].constants[e]]=c[c[t].constants[e]];b[s].interfaces.push(c)}}}function y(a){if(i(a.prototype,"$binds")){var b=p(a.prototype.$binds);j(a[s].binds,b),delete a.prototype.$binds}}function z(a,d,e){var f,g,h={};if(i(a,"$statics")){for(f in a.$statics)g=a.$statics[f],c(g)&&!g[s]&&!g[t]?(n(d[s].staticMethods,f),g["$constructor_"+d[s].id]=d,g.$name=f):d[s].staticProperties[f]=g,d[f]=g;delete a.$statics}i(a,"$binds")&&(h.$binds=a.$binds,delete a.$binds),i(a,"$borrows")&&(h.$borrows=a.$borrows,delete a.$borrows),i(a,"$implements")&&(h.$implements=a.$implements,delete a.$implements),i(a,"$abstracts")&&(h.$abstracts=a.$abstracts,delete a.$abstracts);for(f in a)g=a[f],c(g)&&!g[s]&&!g[t]?(g["$prototype_"+d[s].id]=d.prototype,g.$name=f):b(g)||n(d[s].properties,f),e&&(d.prototype[f]=g);l(a,h)}function A(a,b){var c,d,e={},f={};i(a,"$constants")&&(e.$constants=a.$constants,f.$constants=!0,delete a.$constants),i(a,"$finals")&&(e.$finals=a.$finals,f.$finals=!0,delete a.$finals),z(a,b);if(f.$constants)for(c in e.$constants)d=e.$constants[c],b[s].staticProperties[c]=d,b[c]=d;f.$finals&&z(e.$finals,b,!0)}function B(a,b){var c,d;for(c=a.length-1;c>=0;c-=1)d=b[a[c]],b[a[c]]=o(d,b),b[a[c]]["$prototype_"+b.$constructor[s].id]=d["$prototype_"+b.$constructor[s].id],b[a[c]].$name=d.$name}function C(){var a=function(){var a,b;b=this.$constructor[s].properties;for(a=b.length;a>=0;a-=1)this[b[a]]=v(this[b[a]]);this.$constructor[s].binds.length&&B(this.$constructor[s].binds,this,this),this.initialize.apply(this,arguments)};return a[s]={staticMethods:[],staticProperties:{},properties:[],interfaces:[],binds:[]},a}function D(a,b){var c,d=b[s].binds,e,f;for(c=d.length-1;c>=0;c-=1)d[c].substr(0,2)!=="__"&&a[s].binds.push(d[c]);m(a[s].properties,b[s].properties),m(a[s].staticMethods,b[s].staticMethods);for(c=b[s].staticMethods.length-1;c>=0;c-=1)b[s].staticMethods[c].substr(0,2)!=="__"&&(a[b[s].staticMethods[c]]=b[b[s].staticMethods[c]]);for(e in b[s].staticProperties)f=b[s].staticProperties[e],e.substr(0,2)!=="__"&&(a[s].staticProperties[e]=f,a[e]=v(f));a[s].interfaces=[].concat(b[s].interfaces)}function E(a){return function b(){var c=b.caller||arguments.callee.caller||arguments.caller;return c["$prototype_"+a].$constructor.$parent.prototype[c.$name].apply(this,arguments)}}function F(a){return function b(){var c=b.caller||arguments.callee.caller||arguments.caller;return c["$prototype_"+a].$constructor}}function G(a){return function b(){var c=b.caller||arguments.callee.caller||arguments.caller;return c["$constructor_"+a].$parent[c.$name].apply(this,arguments)}}var q,r=0,s="$class",t="$interface",u;return u=function(){return this.$constructor},q=function(b){delete b.$name;var c,d;return i(b,"$extends")?(d=b.$extends,delete b.$extends,b.initialize=b.initialize||function(){d.prototype.initialize.apply(this,arguments)},c=C(),c.$parent=d,c[s].id=d[s].id,c.prototype=h(d.prototype,b),D(c,d)):(b.initialize=b.initialize||function(){},c=C(),c[s].id=r+=1,c.prototype=b),A(b,c),c.$parent||(c.prototype.$super=E(c[s].id),c.prototype.$self=F(c[s].id),c.prototype.$static=u),c.prototype.$constructor=c,c.$super=G(c[s].id),w(c),y(c),i(b,"$implements")&&(x(b.$implements,c),delete c.prototype.$implements),i(b,"$abstracts")&&delete b.$abstracts,c},q}),c("AbstractClass",["Utils/object/hasOwn","./Class"],function(b,c){function e(a){var e;return b(a,"$abstracts")&&delete a.$abstracts,e=c(a),e[d]=!0,e}var d="$abstract";return e}),c("Interface",["Utils/object/hasOwn","Utils/lang/toArray"],function(b,c){function e(a){delete a.$name;var e,f,g,h,i=function(){};i[d]={parents:[],constants:[]};if(b(a,"$extends")){e=c(a.$extends),f=e.length;for(f-=1;f>=0;f-=1){h=e[f];for(g=h[d].constants.length-1;g>=0;g-=1)i[h[d].constants[g]]=h[h[d].constants[g]];i[d].parents.push(h)}delete a.$extends}if(b(a,"$constants"))for(f in a.$constants)i[f]=a.$constants[f],i[d].constants.push(f);return i}var d="$interface";return e}),c("FinalClass",["./Class"],function(b){return function(c){var d=new b(c);return d}}),c("instanceOf",[],function(){function c(a,d){var e,f=a[b].parents;for(e=f.length-1;e>=0;e-=1){if(f[e]===d)return!0;if(c(a,f[e]))return!0}return!1}function d(b,d){var e,f=b.$constructor[a].interfaces;for(e=f.length-1;e>=0;e-=1)if(f[e]===d||c(f[e],d))return!0;return!1}function e(c,e){return c.$constructor[a]&&e[b]?d(c,e):c instanceof e}var a="$class",b="$interface";return e}),c("classify",["./Class","./AbstractClass","./Interface","./FinalClass","instanceOf"],function(a,b,c,d,e){var f={},g;f.Class=a,f.AbstractClass=b,f.Interface=c,f.FinalClass=d,f.instanceOf=e;if(typeof module!="undefined"&&typeof exports!="undefined"&&module.exports)module.exports=f;else{g=typeof window!="undefined"&&window.navigator&&window.document?window:global;if(!g)throw new Error("Could not grab global object.");g.Classify=f}})})();


// -------------------------------------------------------------------------

var ClassifyClassPerson = Classify.Class({
  initialize: function(name){
    this.name = name;
  },
  setAddress: function(country, city, street) {
    this.country = country;
    this.city = city;
    this.street = street;
  }
});

var ClassifyClassFrenchGuy = Classify.Class({
  $extends: ClassifyClassPerson,
  setAddress: function(city, street) {
    this.$super("France", city, street);
  }
});

var ClassifyClassParisLover = Classify.Class({
  $extends: ClassifyClassFrenchGuy,
  setAddress: function(street) {
    this.$super('Paris', street);
  }
});

var Classify2ClassPerson = Classify.Class({
  initialize: function(name){
    this.name = name;
  },
  setAddress: function(country, city, street) {
    this.country = country;
    this.city = city;
    this.street = street;
  }
});

var Classify2ClassFrenchGuy = Classify.Class({
  $extends: ClassifyClassPerson,
  setAddress: function(city, street) {
    Classify2ClassFrenchGuy.$parent.prototype.setAddress.call(this, "France", city, street);
  }
});

var Classify2ClassParisLover = Classify.Class({
  $extends: ClassifyClassFrenchGuy,
  setAddress: function(street) {
    Classify2ClassParisLover.$parent.prototype.setAddress.call(this, 'Paris', street);
  }
});
</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
JSFace
var p3 = new JSFaceParisLover("Mary");
p3.setAddress("CH");
pending…
my.Class
var p6 = new MyParisLover("Mary");
p6.setAddress("CH");
pending…
John Resig Class
var p9 = new JRParisLover("Mary");
p9.setAddress("CH");
pending…
Klass
var p12 = new EnderParisLover("Mary");
p12.setAddress("CH");
pending…
Classy
var p15 = new ClassyParisLover("Mary");
p15.setAddress("CH");
pending…
PTClass
var p18 = new PTClassParisLover("Mary");
p18.setAddress("CH");
pending…
Classify
var p19 = new ClassifyClassParisLover("Mary");
p19.setAddress("CH");
pending…
Classify $super alternative
var p20 = new Classify2ClassParisLover("Mary");
p20.setAddress("CH");
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