Given this very familiar model of prototypal construction:
function Rectangle(w,h) {
this.width = w;
this.height = h;
}
Rectangle.prototype.area = function() {
return this.width * this.height;
};
Can anyone explain why calling new Rectangle(2,3)
is consistently 10x FASTER than calling Rectangle(2,3)
without the 'new' keyword? I would have assumed that because new adds more plexity to the execution of a function by getting prototypes involved, it would be slower.
Example:
var myTime;
function startTrack() {
myTime = new Date();
}
function stopTrack(str) {
var diff = new Date().getTime() - myTime.getTime();
println(str + ' time in ms: ' + diff);
}
function trackFunction(desc, func, times) {
var i;
if (!times) times = 1;
startTrack();
for (i=0; i<times; i++) {
func();
}
stopTrack('(' + times + ' times) ' + desc);
}
var TIMES = 1000000;
trackFunction('new rect classic', function() {
new Rectangle(2,3);
}, TIMES);
trackFunction('rect classic (without new)', function() {
Rectangle(2,3);
}, TIMES);
Yields (in Chrome):
(1000000 times) new rect classic time in ms: 33 (1000000 times) rect classic (without new) time in ms: 368 (1000000 times) new rect classic time in ms: 35 (1000000 times) rect classic (without new) time in ms: 374 (1000000 times) new rect classic time in ms: 31 (1000000 times) rect classic (without new) time in ms: 368
Given this very familiar model of prototypal construction:
function Rectangle(w,h) {
this.width = w;
this.height = h;
}
Rectangle.prototype.area = function() {
return this.width * this.height;
};
Can anyone explain why calling new Rectangle(2,3)
is consistently 10x FASTER than calling Rectangle(2,3)
without the 'new' keyword? I would have assumed that because new adds more plexity to the execution of a function by getting prototypes involved, it would be slower.
Example:
var myTime;
function startTrack() {
myTime = new Date();
}
function stopTrack(str) {
var diff = new Date().getTime() - myTime.getTime();
println(str + ' time in ms: ' + diff);
}
function trackFunction(desc, func, times) {
var i;
if (!times) times = 1;
startTrack();
for (i=0; i<times; i++) {
func();
}
stopTrack('(' + times + ' times) ' + desc);
}
var TIMES = 1000000;
trackFunction('new rect classic', function() {
new Rectangle(2,3);
}, TIMES);
trackFunction('rect classic (without new)', function() {
Rectangle(2,3);
}, TIMES);
Yields (in Chrome):
Share Improve this question asked Mar 24, 2010 at 15:31 Matthew TaylorMatthew Taylor 3,9614 gold badges31 silver badges33 bronze badges(1000000 times) new rect classic time in ms: 33 (1000000 times) rect classic (without new) time in ms: 368 (1000000 times) new rect classic time in ms: 35 (1000000 times) rect classic (without new) time in ms: 374 (1000000 times) new rect classic time in ms: 31 (1000000 times) rect classic (without new) time in ms: 368
1 Answer
Reset to default 17When you call the function without "new", what is it that you suspect "this" is pointing to? It'll be "window." Updating that is slower than updating the freshly-built new object you'll be using when you invoke it with "new".
Change the second version to this:
trackFunction('rect classic (without new)', function() {
Rectangle.call({}, 2,3);
}, TIMES);
and see what you get. Another thing to try would be this:
trackFunction('rect with constant object', (function() {
var object = { height: 0, width: 0 };
return function() {
Rectangle.call(object, 2, 3);
};
})());
That will save on the cost of rebuilding the dummy object on each iteration.