Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling function using 'new' is less expensive than without it?

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 complexity 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
like image 409
Matthew Taylor Avatar asked Mar 24 '10 15:03

Matthew Taylor


1 Answers

When 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.

like image 62
Pointy Avatar answered Sep 23 '22 20:09

Pointy