I recently tried to optimize some code for an often created value object. (A three dimensional vector, fwiw)
One thing I tried was to convert the constructor function from an anonymous method factory pattern to a normal JavaScript constructor.
This led to a severe performance penalty which surprised me, since the use of 'new' and normal constructors was much recommended in my last question on the subject of JavaScript constructor/factory patterns.
It could well be that my test is too simplistic, or just plain wrong, or a result of recent performance optimizations made in chrome's JavaScript engine, or all of the above. In any case, I'd really like to know why my 'optimizations' led to performance drop - and - most important: Is there any obvious problem with my jsperf testrun?
A constructor is a special function that creates and initializes an object instance of a class. In JavaScript, a constructor gets called when an object is created using the new keyword. The purpose of a constructor is to create a new object and set values for any existing object properties.
'Prototype' helps remove code redundancy which helps boost your app's performance. If you are seeking to optimize resources or memory on your application, you should use prototype .
It is NOT 'bad' to use the new keyword. But if you forget it, you will be calling the object constructor as a regular function. If your constructor doesn't check its execution context then it won't notice that 'this' points to different object (ordinarily the global object) instead of the new instance.
The new keyword has to be placed before the constructor function call and will do the following things: Creates a new object. Sets the prototype of this object to the constructor function's prototype property. Binds the this keyword to the newly created object and executes the constructor function.
The major differences between your tests are:
{}
is way faster than new Object
, which suggests that new
is simply slower than using {}
. (The same is true of []
and new Array
.)
Your tests produce different results: the result of your make
factory function isn't a Make
object. The constructed Make
has a prototype, shared by all Make
objects. Your result of your factory function is just a bare Object
, and has a single prototype in its prototype chain (Object.prototype
), whereas the Make constructed object has two (Make.prototype
, followed by Object.prototype
).
I made a fork of your test, with a factory function that actually returns a Make
object (instead a simple Object
), using the non-standard __proto__
property, and it is much slower than a using a constructor. IE does not support __proto__
, but the results from Firefox and Chrome look pretty definitive.
One of the things that a constructor function optimizes for is shared properties, usually methods. If a number of objects use the same functions as methods, or share other named properties, then one assignment to the prototype will share a single instance of the property among all objects created from the constructor, reducing memory overhead, and will not need to repeat the assignment of each such property for every object created, reducing construction time overhead.
Since your sample does not include any such properties, you're not going to see such benefits. But if your production code does not include shared properties for your constructed object, there might well be no reason to switch to a constructor.
So, if, for example you had code like this:
function make(p) {
return {
parm: p,
addTwo: function() {return this.parm + 2;},
double: function() {return this.parm * 2;},
square: function() {return this.parm * this.parm;}
};
};
it will probably run more slowly than this:
function Make(p) {
this.parm = p;
}
Make.prototype.addTwo = function() {return this.parm + 2;};
Make.prototype.double = function() {return this.parm * 2;}
Make.prototype.square = function() {return this.parm * this.parm;}
It will also take a lot more memory if you create many instances.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With