Вызов функции с использованием «new» дешевле, чем без него? - PullRequest
12 голосов
/ 24 марта 2010

Учитывая эту очень знакомую модель конструкции прототипа:

function Rectangle(w,h) {
    this.width = w;
    this.height = h;
}
Rectangle.prototype.area = function() { 
    return this.width * this.height;
};

Кто-нибудь может объяснить, почему вызов new Rectangle(2,3) всегда в 10 раз быстрее, чем Rectangle(2,3) без ключевого слова "new"? Я предположил бы, что, поскольку new добавляет больше сложности выполнению функции, вовлекая прототипы, это будет медленнее.

Пример:

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);

Выход (в 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

1 Ответ

17 голосов
/ 24 марта 2010

Когда вы вызываете функцию без «new», на что вы подозреваете «this»? Это будет "окно". Обновление выполняется медленнее, чем обновление только что созданного нового объекта, который вы будете использовать при вызове его с помощью «new».

Измените вторую версию на эту:

trackFunction('rect classic (without new)', function() {
    Rectangle.call({}, 2,3);
}, TIMES);

и посмотри, что получишь. Еще одна вещь, которую стоит попробовать:

trackFunction('rect with constant object', (function() {
  var object = { height: 0, width: 0 };
  return function() {
    Rectangle.call(object, 2, 3);
  };
})());

Это сэкономит на стоимости восстановления фиктивного объекта на каждой итерации.

...