2010-03-24 4 views
12

Donné ce modèle très familier de la construction prototypique:Appelant la fonction en utilisant «nouveau» est moins cher que sans elle?

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

Quelqu'un peut-il expliquer pourquoi appeler new Rectangle(2,3) est toujours plus rapide que d'appeler 10x Rectangle(2,3) sans le « nouveau » mot-clé? J'aurais supposé que parce que le nouveau ajoute plus de complexité à l'exécution d'une fonction en impliquant des prototypes, il serait plus lent.

Exemple:

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

Les rendements (en 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 

Répondre

17

Lorsque vous appelez la fonction sans "nouvelle", qu'est-ce que vous pensez "ce" est pointant vers? Ce sera "fenêtre". La mise à jour est plus lente que la mise à jour du nouvel objet que vous allez utiliser lorsque vous l'appelez "nouveau".

Modifier la deuxième version à ceci:

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

et voir ce que vous obtenez. Une autre chose à essayer serait ceci:

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

Cela permettra d'économiser sur le coût de la reconstruction de l'objet factice à chaque itération.

+0

Vous avez absolument raison. Merci! –

+0

Lorsque je fais cela ci-dessus, j'obtiens environ 148 ms d'exécution sur le nouvel objet. Pas aussi rapide que d'appeler nouveau, mais beaucoup plus rapide que de toucher le document. –

+0

Droit - notez également que dans la deuxième version il y a la surcharge d'appeler la fonction "appel" aussi. Je soupçonne que V8 a une mise en œuvre assez bien optimisée de "nouveau" (en fait, c'est assez clair à partir de vos chiffres)! – Pointy

Questions connexes