The Benchmark Logic
Pretty simple, create a new object with a "privileged property" plus an inherited one. The test prototype looks like this object:
var proto = {toString:function () {
return this.name;
}}
The assumption is that somehow the object should be able to return it's name, which is not shared via prototype.
ES3 Game
I hope I don't have to explain this piece of code:
function F(name) {
this.name = name;
}
F.prototype = proto;
To test above classical pattern, all we need is to confirm this behavior:
var o = new F("instance");
alert(String(o) === "instance");
ES5 Game
Using an updated browser, it should be possible to replicate ES3 behavior via this piece of code:
var o = Object.create(proto, {
name: {
value:"object"
}
});
Right, Object.create comes with much more power than a simple property assignment, but here we are testing a basic task just to analyze what's the outcome, right? Just to be sure about the result:
alert(String(o) === "object");
Optimized ES5 Game
What can we do to improve performances? Avoid global scope look up, the Object constructor, plus use a static/fixed property to cheat the test:
var fixed = {
name: {
value: "static"
}
};
var create = Object.create;
var o = create(proto, fixed);
// the assertion
alert(String(o) === "static");
The Benchmark
Let's put these patterns together inside a closure, execute them 100000 times, retrieving elapsed time.
setTimeout(function () {
var proto = {toString:function () {
return this.name;
}};
var fixed = {
name: {
value: "static"
}
};
function F(name) {
this.name = name;
}
F.prototype = proto;
var o;
for(var i = 100000, instance = new Date; i--;) {
o = new F("instance");
}
instance -= new Date;
for(var i = 100000, object = new Date; i--;) {
o = Object.create(proto, {
name: {
value:"object"
}
});
}
object -= new Date;
for(var create = Object.create,
i = 100000, static = new Date; i--;
) {
o = create(proto, fixed);
}
static -= new Date;
alert([instance, object, static].join("\n").replace(/-/g,"ms: "));
}, 1000);
The Result
Based on Atom N270 nad testing via Chrome 5 for devs, this is what I read in the alert:
ms: 7
ms: 2325
ms: 2218
The first result goes up to 54ms, reaching 5ms, the second one is pretty much stable while the latest one goes down 'till 1987 ms ...
Conclusion
new Constructor seems to be the best option for those cases where the initialize/init/construct method needs to somehow setup the created instance. Only if we need special Object.create features it is worth it to use it, but if we base a whole framework over Object.create, considering eventually emulations for old browsers, this framework will be inevitably slower than older code. This means that as example a classic Point class option, should still be exactly like this:
function Point(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
or eventually like the next one, if we don't need chained methods, neither new before each call:
function Point(x, y, z) {
return {x:x, y:y, z:z};
}
by my good old AStar algorithm time, the fastest option ever!