Подтвердить что ты не робот

Функция вызова с использованием "новой" дешевле, чем без нее?

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

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

Может ли кто-нибудь объяснить, почему вызов new Rectangle(2,3) постоянно 10x FASTER, чем вызов Rectangle(2,3) без ключевого слова '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
4b9b3361

Ответ 1

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

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

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

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