Type.js versus Class.js
JavaScript performance comparison
Info
Testing performance of stripped down inheritance versus John Resig's Class.js. Class.js appears to slow down the further down the inheritance tree you go, while Type.js does not.
Preparation code
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.1/lodash.min.js">
</script>
<script>
Benchmark.prototype.setup = function() {
var data = [{
"name": "2% Milk",
"unit": "Cup",
"p": 8,
"f": 5,
"c": 12,
"_id": "512ae0c67fdfe7e449000001",
"__v": 0
}, {
"name": "2% Shredded Cheddar Cheese",
"unit": "Cup",
"p": 28,
"f": 24,
"c": 0,
"_id": "512ae0c67fdfe7e449000002",
"__v": 0
}, {
"name": "Almonds - Sliced",
"unit": "Tbsp",
"p": 2,
"f": 4,
"c": 1,
"_id": "512ae0c67fdfe7e449000003",
"__v": 0
}, {
"name": "Banana",
"unit": "Ounce",
"p": 0,
"f": 0,
"c": 6,
"_id": "512ae0c67fdfe7e449000004",
"__v": 0
}, {
"name": "Banana Chocolate Chip Muffin",
"unit": "Muffin",
"p": 2.25,
"f": 2.75,
"c": 21.75,
"_id": "512b8c4fcac258a65c000001",
"__v": 0
}, {
"name": "Boar's Head Sweet Slice Ham",
"unit": "Ounce",
"p": 5,
"f": 1.25,
"c": 0.5,
"_id": "512ae0c67fdfe7e449000005",
"__v": 0
}, {
"name": "Broccoli",
"unit": "100g",
"p": 2,
"f": 0,
"c": 7,
"_id": "512ae0c67fdfe7e449000006",
"__v": 0
}, {
"name": "Chicken Breast",
"unit": "Ounce",
"p": 8.7,
"f": 1,
"c": 0,
"_id": "512ae0c67fdfe7e449000007",
"__v": 0
}, {
"name": "Chicken Thigh",
"unit": "Ounce",
"p": 4.5,
"f": 4.7,
"c": 0,
"_id": "512ae0c67fdfe7e449000008",
"__v": 0
}, {
"name": "Chipotle Bowl: Chicken, Cheese",
"unit": "Serving",
"p": 48,
"f": 21,
"c": 55,
"_id": "512ae0c67fdfe7e449000009",
"__v": 0
}, {
"name": "Chipotle Bowl: Chicken, Sour Cream, Cheese",
"unit": "Serving",
"p": 50,
"f": 31,
"c": 57,
"_id": "512ae0c67fdfe7e44900000a",
"__v": 0
}, {
"name": "Chipotle Salad: Chicken, Cheese",
"unit": "Serving",
"p": 46,
"f": 17,
"c": 25,
"_id": "512ae0c67fdfe7e44900000b",
"__v": 0
}, {
"name": "Chipotle Salad: Chicken, Sour Cream, Cheese",
"unit": "Serving",
"p": 48,
"f": 27,
"c": 27,
"_id": "512ae0c67fdfe7e44900000c",
"__v": 0
}, {
"name": "Chipotle Salad: Chicken, Sour Cream, Cheese, Dressing",
"unit": "Serving",
"p": 48,
"f": 51.5,
"c": 39,
"_id": "512ae0c67fdfe7e44900000d",
"__v": 0
}, {
"name": "Chipotle: Black Beans",
"unit": "Serving",
"p": 7,
"f": 1,
"c": 23,
"_id": "512ae0c67fdfe7e44900000e",
"__v": 0
}, {
"name": "Chipotle: Cheese",
"unit": "Serving",
"p": 8,
"f": 8.5,
"c": 0,
"_id": "512ae0c67fdfe7e44900000f",
"__v": 0
}, {
"name": "Chipotle: Chicken",
"unit": "Serving",
"p": 32,
"f": 6.5,
"c": 1,
"_id": "512ae0c67fdfe7e449000010",
"__v": 0
}, {
"name": "Chipotle: Guacamole",
"unit": "Serving",
"p": 2,
"f": 13,
"c": 8,
"_id": "512ae0c67fdfe7e449000011",
"__v": 0
}, {
"name": "Chipotle: Lettuce",
"unit": "Serving",
"p": 1,
"f": 0,
"c": 2,
"_id": "512ae0c67fdfe7e449000012",
"__v": 0
}, {
"name": "Chipotle: Pinto Beans",
"unit": "Serving",
"p": 7,
"f": 1,
"c": 22,
"_id": "512ae0c67fdfe7e449000013",
"__v": 0
}, {
"name": "Chipotle: Salad Dressing",
"unit": "Serving",
"p": 0,
"f": 24.5,
"c": 12,
"_id": "512ae0c67fdfe7e449000014",
"__v": 0
}, {
"name": "Chipotle: Sour Cream",
"unit": "Serving",
"p": 2,
"f": 10,
"c": 2,
"_id": "512ae0c67fdfe7e449000015",
"__v": 0
}, {
"name": "Chipotle: Steak",
"unit": "Serving",
"p": 30,
"f": 6.5,
"c": 2,
"_id": "512ae0c67fdfe7e449000016",
"__v": 0
}, {
"name": "Colby Cheese",
"unit": "Ounce",
"p": 7,
"f": 9,
"c": 1,
"_id": "512ae0c67fdfe7e449000017",
"__v": 0
}, {
"name": "Cool Whip - Fat Free",
"unit": "Tbsp",
"p": 0,
"f": 0,
"c": 1.5,
"_id": "512ae0c67fdfe7e449000018",
"__v": 0
}, {
"name": "Deli Turkey",
"unit": "Ounce",
"p": 4,
"f": 1,
"c": 2,
"_id": "512ae0c67fdfe7e449000019",
"__v": 0
}, {
"name": "Egg",
"unit": "1 Large",
"p": 6,
"f": 6,
"c": 0,
"_id": "512ae0c67fdfe7e44900001a",
"__v": 0
}, {
"name": "Egg White",
"unit": "1 Large",
"p": 4,
"f": 0,
"c": 0,
"_id": "512ae0c67fdfe7e44900001b",
"__v": 0
}, {
"name": "Feta Cheese",
"unit": "Tbsp",
"p": 1.3,
"f": 2,
"c": 0.375,
"_id": "512ae0c67fdfe7e44900001c",
"__v": 0
}, {
"name": "Harvest Land Turkey Burger",
"unit": "Patty",
"p": 20,
"f": 9,
"c": 0,
"_id": "512ae0c67fdfe7e44900001d",
"__v": 0
}, {
"name": "Hellmann's Light Mayo",
"unit": "Tbsp",
"p": 0,
"f": 3.5,
"c": 0.75,
"_id": "512ae0c67fdfe7e44900001e",
"__v": 0
}, {
"name": "Hershey's Syrup",
"unit": "Tbsp",
"p": 0,
"f": 0,
"c": 12,
"_id": "512ae0c67fdfe7e44900001f",
"__v": 0
}, {
"name": "Jack Link's Peppered Beef Jerky",
"unit": "Ounce",
"p": 15,
"f": 1,
"c": 4,
"_id": "512ae0c67fdfe7e449000020",
"__v": 0
}, {
"name": "Jack Link's Teriyaki Beef Jerky",
"unit": "Ounce",
"p": 14,
"f": 1,
"c": 5,
"_id": "512ae0c67fdfe7e449000021",
"__v": 0
}, {
"name": "Jello Sugar Free Pudding - Chocolate",
"unit": "Serving",
"p": 1,
"f": 1.5,
"c": 13,
"_id": "512ae0c67fdfe7e449000022",
"__v": 0
}, {
"name": "Jello Sugar Free Pudding - Dulce de Leche",
"unit": "Serving",
"p": 1,
"f": 1,
"c": 12,
"_id": "512ae0c67fdfe7e449000023",
"__v": 0
}, {
"name": "Kashi Oatmeal Dark Chocolate Cookie",
"unit": "Cookie",
"p": 2,
"f": 5,
"c": 20,
"_id": "512ae0c67fdfe7e449000024",
"__v": 0
}, {
"name": "Kashi Toasted Berry Crumble",
"unit": "Cup",
"p": 12,
"f": 4.6,
"c": 46.5,
"_id": "512ae0c67fdfe7e449000025",
"__v": 0
}, {
"name": "Kroger Honey Whole Wheat Bread",
"unit": "Slice",
"p": 4,
"f": 1,
"c": 16,
"_id": "512ae0c67fdfe7e449000026",
"__v": 0
}, {
"name": "Kroger Mini Cheese Ravioli",
"unit": "Cup",
"p": 11,
"f": 8,
"c": 35,
"_id": "512ae0c67fdfe7e449000027",
"__v": 0
}, {
"name": "Liberté Greek Yogurt - Blueberry",
"unit": "Serving",
"p": 11,
"f": 0,
"c": 20,
"_id": "512ae0c67fdfe7e449000028",
"__v": 0
}, {
"name": "Liberté Greek Yogurt - Peach/Passion Fruit",
"unit": "Serving",
"p": 11,
"f": 0,
"c": 20,
"_id": "512ae0c67fdfe7e449000029",
"__v": 0
}, {
"name": "Liberté Greek Yogurt - Strawberry",
"unit": "Serving",
"p": 11,
"f": 0,
"c": 20,
"_id": "512ae0c67fdfe7e44900002a",
"__v": 0
}, {
"name": "Light Ranch Dressing",
"unit": "Tbsp",
"p": 0.5,
"f": 4,
"c": 1,
"_id": "512ae0c67fdfe7e44900002b",
"__v": 0
}, {
"name": "Nature's Own Whole Wheat Bread",
"unit": "Slice",
"p": 4,
"f": 1,
"c": 10,
"_id": "512ae0c67fdfe7e44900002c",
"__v": 0
}, {
"name": "Newman's Own Light Balsamic",
"unit": "Tbsp",
"p": 0,
"f": 2,
"c": 2,
"_id": "512ae0c67fdfe7e44900002d",
"__v": 0
}, {
"name": "Oikos Greek Yogurt - Strawberry",
"unit": "Serving",
"p": 12,
"f": 0,
"c": 19,
"_id": "512ae0c67fdfe7e44900002e",
"__v": 0
}, {
"name": "Outback: Filet & Grilled Shrimp",
"unit": "Serving",
"p": 45,
"f": 24,
"c": 6,
"_id": "512ae0c67fdfe7e44900002f",
"__v": 0
}, {
"name": "Outback: Grilled Asparagus",
"unit": "Serving",
"p": 2,
"f": 4,
"c": 3,
"_id": "512ae0c67fdfe7e449000030",
"__v": 0
}, {
"name": "Outback: Grilled Shrimp",
"unit": "Serving",
"p": 28,
"f": 20,
"c": 7,
"_id": "512ae0c67fdfe7e449000031",
"__v": 0
}, {
"name": "Outback: Mixed Veggies",
"unit": "Serving",
"p": 3,
"f": 3,
"c": 11,
"_id": "512ae0c67fdfe7e449000032",
"__v": 0
}, {
"name": "PB2",
"unit": "Tbsp",
"p": 2.5,
"f": 0.75,
"c": 2.5,
"_id": "512ae0c67fdfe7e449000033",
"__v": 0
}, {
"name": "Pita",
"unit": "Serving",
"p": 6,
"f": 0,
"c": 22,
"_id": "512ae0c67fdfe7e449000034",
"__v": 0
}, {
"name": "Pomegranate Dressing",
"unit": "Tbsp",
"p": 0,
"f": 2.25,
"c": 3,
"_id": "512ae0c67fdfe7e449000035",
"__v": 0
}, {
"name": "Pork Chop",
"unit": "Ounce",
"p": 7,
"f": 3,
"c": 0,
"_id": "512ae0c67fdfe7e449000036",
"__v": 0
}, {
"name": "Pork Tenderloin",
"unit": "Ounce",
"p": 7,
"f": 1,
"c": 0,
"_id": "512ae0c67fdfe7e449000037",
"__v": 0
}, {
"name": "Porkolicious BBQ Sauce",
"unit": "Tbsp",
"p": 0,
"f": 0,
"c": 5.5,
"_id": "512ae0c67fdfe7e449000038",
"__v": 0
}, {
"name": "Raspberries",
"unit": "Cup",
"p": 1,
"f": 1,
"c": 15,
"_id": "512ae0c67fdfe7e449000039",
"__v": 0
}, {
"name": "Reduced Sugar Craisins",
"unit": "Tbsp",
"p": 0,
"f": 0,
"c": 7.5,
"_id": "512ae0c67fdfe7e44900003a",
"__v": 0
}, {
"name": "Salami",
"unit": "Ounce",
"p": 4,
"f": 6,
"c": 1,
"_id": "512ae0c67fdfe7e44900003b",
"__v": 0
}, {
"name": "Shredded Cheddar Cheese",
"unit": "Cup",
"p": 28,
"f": 36,
"c": 2,
"_id": "512ae0c67fdfe7e44900003c",
"__v": 0
}, {
"name": "Skyline: 4-Way Onion",
"unit": "Serving",
"p": 48,
"f": 41,
"c": 58,
"_id": "512ae0c67fdfe7e44900003d",
"__v": 0
}, {
"name": "Skyline: Cheese Coney",
"unit": "Serving",
"p": 20,
"f": 23,
"c": 24,
"_id": "512ae0c67fdfe7e44900003e",
"__v": 0
}, {
"name": "Skyline: Chili Cheese Sandwich",
"unit": "Serving",
"p": 20,
"f": 18,
"c": 24,
"_id": "512ae0c67fdfe7e44900003f",
"__v": 0
}, {
"name": "Spinach (Raw)",
"unit": "100g",
"p": 3,
"f": 0,
"c": 4,
"_id": "512ae0c67fdfe7e449000040",
"__v": 0
}, {
"name": "Starbucks Grande 2% Latte",
"unit": "Serving",
"p": 12,
"f": 7,
"c": 18,
"_id": "512ae0c67fdfe7e449000041",
"__v": 0
}, {
"name": "Starbucks Grande 2% Mocha",
"unit": "Serving",
"p": 13,
"f": 8,
"c": 42,
"_id": "512ae0c67fdfe7e449000042",
"__v": 0
}, {
"name": "Starbucks Grande Nonfat Latte",
"unit": "Serving",
"p": 13,
"f": 0,
"c": 19,
"_id": "512ae0c67fdfe7e449000043",
"__v": 0
}, {
"name": "Starbucks Grande Nonfat Mocha",
"unit": "Serving",
"p": 13,
"f": 2.5,
"c": 43,
"_id": "512ae0c67fdfe7e449000044",
"__v": 0
}, {
"name": "Starbucks Iced Grande 2% Mocha",
"unit": "Serving",
"p": 9,
"f": 6,
"c": 36,
"_id": "512ae0c67fdfe7e449000045",
"__v": 0
}, {
"name": "Starbucks Iced Grande Nonfat Mocha",
"unit": "Serving",
"p": 9,
"f": 2.5,
"c": 37,
"_id": "512ae0c67fdfe7e449000046",
"__v": 0
}, {
"name": "Strawberries",
"unit": "Cup",
"p": 1,
"f": 0,
"c": 12,
"_id": "512ae0c67fdfe7e449000047",
"__v": 0
}, {
"name": "Sweet Potato - Mashed",
"unit": "Cup",
"p": 4,
"f": 0,
"c": 42,
"_id": "512ae0c67fdfe7e449000048",
"__v": 0
}, {
"name": "Target 1% Cottage Cheese",
"unit": "Cup",
"p": 22,
"f": 2,
"c": 12,
"_id": "512ae0c67fdfe7e449000049",
"__v": 0
}, {
"name": "Target Honey Ham",
"unit": "Ounce",
"p": 5,
"f": 0.75,
"c": 1.5,
"_id": "512ae0c67fdfe7e44900004a",
"__v": 0
}, {
"name": "Thomas' English Muffin",
"unit": "Serving",
"p": 4,
"f": 1,
"c": 25,
"_id": "512ae0c67fdfe7e44900004b",
"__v": 0
}, {
"name": "Turkey Bacon",
"unit": "Slice",
"p": 2,
"f": 0,
"c": 2,
"_id": "512ae0c67fdfe7e44900004c",
"__v": 0
}, {
"name": "White Castle: Bacon, Egg & Cheese Sandwich",
"unit": "Serving",
"p": 12,
"f": 12,
"c": 13,
"_id": "512ae0c67fdfe7e44900004d",
"__v": 0
}, {
"name": "White Castle: Cheese Stick",
"unit": "Stick",
"p": 4,
"f": 11,
"c": 7,
"_id": "512ae0c67fdfe7e44900004e",
"__v": 0
}, {
"name": "White Castle: Cheeseburger",
"unit": "Serving",
"p": 8,
"f": 9,
"c": 15,
"_id": "512ae0c67fdfe7e44900004f",
"__v": 0
}, {
"name": "White Castle: Egg & Cheese Sandwich",
"unit": "Serving",
"p": 9,
"f": 7,
"c": 13,
"_id": "512ae0c67fdfe7e449000050",
"__v": 0
}, {
"name": "White Castle: Hash Rounds (Small)",
"unit": "Serving",
"p": 2,
"f": 4,
"c": 25,
"_id": "512ae0c67fdfe7e449000051",
"__v": 0
}, {
"name": "Wholly Guacamole",
"unit": "Tbsp",
"p": 0.5,
"f": 2.5,
"c": 1.5,
"_id": "512ae0c67fdfe7e449000052",
"__v": 0
}];
(function() {
var initializing = false,
fnTest = /xyz/.test(function() {
xyz;
}) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
this.Class = function() {};
// Create a new Class that inherits from this class
Class.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 Class() {
// All construction is actually done in the init method
if (!initializing && this.init) this.init.apply(this, arguments);
}
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;
// And make this class extendable
Class.extend = arguments.callee;
return Class;
};
})();
(function() {
Type = function(child) {
this._child = child;
this._child.prototype.merge = function(src, overwrite) {
for (var prop in src) {
if (overwrite || !this.hasOwnProperty(prop)) {
this[prop] = src[prop];
}
}
return this;
};
this.extend = function(parent) {
this._child.prototype = new parent;
return this;
}
this.from = function(obj) {
for (var prop in obj) {
if (this._child.prototype[prop]) {
this._child.prototype['_' + prop] = this._child.prototype[prop];
}
this._child.prototype[prop] = obj[prop];
}
return this._child;
}
return this;
};
})();
var FirstClass = Class.extend({
init: function() {
return 'FirstClass init';
},
name: null,
unit: null,
p: null,
f: null,
c: null
});
var SecondClass = FirstClass.extend({
init: function() {
return 'SecondClass ' + this._super();
}
});
var ThirdClass = SecondClass.extend({
init: function() {
return 'ThirdClass ' + this._super();
}
});
var FourthClass = ThirdClass.extend({
init: function() {
return 'FourthClass ' + this._super();
}
});
var FirstType = Type(function FirstType() {
return 'FirstType ctor';
}).from({
name: null,
unit: null,
p: null,
f: null,
c: null
});
var SecondType = Type(function SecondType() {
return 'SecondType ' + this.constructor.apply(this, arguments);
}).extend(FirstType).from({});
var ThirdType = Type(function ThirdType() {
return 'ThirdType ' + this.constructor.apply(this, arguments);
}).extend(SecondType).from({});
var FourthType = Type(function FourthType() {
return 'FourthType ' + this.constructor.apply(this, arguments);
}).extend(ThirdType).from({});
};
Benchmark.prototype.teardown = function() {
data = Class = Type = null;
FirstClass = SecondClass = ThirdClass = FourthClass = null;
FirstType = SecondType = ThirdType = FourthType = null;
};
</script>
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
FirstClass |
|
pending… |
SecondClass |
|
pending… |
ThirdClass |
|
pending… |
FourthClass |
|
pending… |
FirstType |
|
pending… |
SecondType |
|
pending… |
ThirdType |
|
pending… |
FourthType |
|
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:
- Revision 1: published by Ben Clinkinbeard
- Revision 2: published by Ben Clinkinbeard
- Revision 3: published by Ben Clinkinbeard
0 comments