2009-08-23 52 views
2

鑑於此代碼:優化建議的Javascript

var minX = minY = maxX = maxY = 0; 

    for(var i=0; i<objArray.length; i++){ 
     if(objArray[i].x < minX){ 
      minX = objArray[i].x; 
     }else if(objArray [i].x > maxX){ 
      maxX = objArray[i].x; 
     } 
     if(objArray[i].y < minY){ 
      minY = objArray[i].y; 
     }else if(objArray [i].y > maxY){ 
      maxY = objArray[i].y; 
     } 
    } 

它的工作原理,但我不認爲這是非常優雅。 這是簡單的邏輯,但它使用10行代碼。可以改進嗎?

回答

10

你可以使用Math.minMath.max

var minX = minY = Number.POSITIVE_INFINITY, 
    maxX = maxY = Number.NEGATIVE_INFINITY; 

for(var i=0; i<objArray.length; i++){ 
    minX = Math.min(objArray[i].x, minX); 
    minY = Math.min(objArray[i].y, minY); 
    maxX = Math.max(objArray[i].x, maxX); 
    maxY = Math.max(objArray[i].y, maxY); 
} 

For循環速度優化,你可以存儲長度只計算一次:

for(var i=0, len = objArray.length; i<len; i++){ 
    //... 
} 

檢查這個article有關循環優化的詳細信息。

另一種方法,只是爲了「好玩的功能」,因爲我不會推薦它性能,可以使用Array.map x和y的值分開到兩個數組,然後調用MIN和MAX函數與apply

var allX = objArray.map(function (o) { return o.x; }); 
var allY = objArray.map(function (o) { return o.y; }); 

minX = Math.min.apply(Math, allX); 
minY = Math.min.apply(Math, allY); 
maxX = Math.max.apply(Math, allX); 
maxY = Math.max.apply(Math, allY); 

這是如何工作的?

apply函數用於調用具有給定上下文和參數的另一個函數,並將其作爲數組提供。在MIN和MAX函數可以利用輸入參數的任意數目:Math.max(VAL1,VAL2,...,VALN)

因此,如果我們致電:

Math.min.apply(Math, [1,2,3,4]); 

功能將執行適用:

Math.min(1,2,3,4); 

注意,第一個參數,上下文,是不是這些功能很重要,因爲它們是靜態的,他們會不管什麼作爲上下文傳遞工作。

+0

現在需要另一個編輯 - 仍然很好的工作。 – 2009-08-23 07:20:48

+0

@安迪:編輯,謝謝! – CMS 2009-08-23 07:46:21

1

迄今爲止所有的答案似乎都是在比較中使用未初始化的變量(minX等)。這是一個功能性的,優雅的解決方案:

var minX = anarray.reduce(function(a,b) { return {x : Math.min(a.x,b.x)};}).x; 
var minY = anarray.reduce(function(a,b) { return {y : Math.min(a.y,b.y)};}).y; 
var maxX = anarray.reduce(function(a,b) { return {x : Math.max(a.x,b.x)};}).x; 
var maxY = anarray.reduce(function(a,b) { return {y : Math.max(a.y,b.y)};}).y; 

here爲減少功能的解釋以及如何使其能夠在不支持它本身的瀏覽器。

5

它最多使用10行代碼。

但是,LoC不是優化的度量。

我在Firefox 3.5中測試了上述算法。 (請參閱以下測試用例。)

您的原始代碼(methodA)幾乎是CMS(methodB)的兩倍! Math.min的使用使得他的版本更具可讀性,並且在大多數情況下,這是重要的。但它確實引入了更多的查找和函數調用,並且降低了查詢速度。

'功能性趣味'版本(methodC)實際上比任一版本都快得多!這對我來說是一個驚喜,因爲這個版本必須建立兩個臨時數組,但似乎apply()在一次性完成所有比較中的很好用法彌補了這一點。然而,這是在Firefox上,那裏有一個本地實現的Array.map()。像IE這樣的瀏覽器如果沒有這個功能,就需要在Array原型中加入一個JavaScript版本,這使得methodC對methodB和methodB一樣慢。

史蒂夫的替代功能版本,正如所料,非常緩慢;所有這些臨時物體都會造成損失。

最後,我管理得最快的是通過採用原始方法A並調整它以刪除每循環.length訪問,並微調多個屬性訪問。令人驚訝的是這(方法E)敲了一下。

但是,所有這些通常都是針對瀏覽器的。我只在一個瀏覽器上測試過;你可能在別人身上得到不同的結果。通常,微型優化並沒有得到回報,你最好選擇最具可讀性的選項。

<script type="text/javascript"> 
    var objArray= []; 
    for (var i= 0; i<1000000; i++) { 
     objArray.push({'x': Math.floor(Math.random()*100000), 'y': Math.floor(Math.random()*100000)}); 
    } 

    function methodA() { 
     var t= new Date(); 
     var minX = minY = maxX = maxY = 0; 
     for(var i=0; i<objArray.length; i++){ 
       if(objArray[i].x < minX){ 
         minX = objArray[i].x; 
       }else if(objArray [i].x > maxX){ 
         maxX = objArray[i].x; 
       } 
       if(objArray[i].y < minY){ 
         minY = objArray[i].y; 
       }else if(objArray [i].y > maxY){ 
         maxY = objArray[i].y; 
       } 
     } 
     alert(new Date()-t); 
    } 
    function methodB() { 
     var t= new Date(); 
     var minX = minY = Number.POSITIVE_INFINITY, 
      maxX = maxY = Number.NEGATIVE_INFINITY; 
     for(var i=0; i<objArray.length; i++){ 
      minX = Math.min(objArray[i].x, minX); 
      minY = Math.min(objArray[i].y, minY); 
      maxX = Math.max(objArray[i].x, maxX); 
      maxY = Math.max(objArray[i].y, maxY); 
     } 
     alert(new Date()-t); 
    } 
    function methodC() { 
     var t= new Date(); 
     var allX = objArray.map(function (o) { return o.x; }); 
     var allY = objArray.map(function (o) { return o.y; }); 

     minX = Math.min.apply(Math, allX); 
     minY = Math.min.apply(Math, allY); 
     maxX = Math.max.apply(Math, allX); 
     maxY = Math.max.apply(Math, allY); 
     alert(new Date()-t); 
    } 
    function methodD() { 
     var t= new Date(); 
     var minX = objArray.reduce(function(a,b) { return {x : Math.min(a.x,b.x)};}).x; 
     var minY = objArray.reduce(function(a,b) { return {y : Math.min(a.y,b.y)};}).y; 
     var maxX = objArray.reduce(function(a,b) { return {x : Math.max(a.x,b.x)};}).x; 
     var maxY = objArray.reduce(function(a,b) { return {y : Math.max(a.y,b.y)};}).y; 
     alert(new Date()-t); 
    } 
    function methodE() { 
     var t= new Date(); 
     var minX = minY = maxX = maxY = 0; 
     var o, v; 
     for (var i=objArray.length; i-->0;) { 
      o= objArray[i]; 
      v= o.x; 
      if (v<minX) minX= v; 
      if (v>maxX) maxX= v; 
      v= o.y; 
      if (v<minY) minY= v; 
      if (v>maxY) maxY= v; 
     } 
     alert(new Date()-t); 
    } 
</script> 
<button onclick="methodA()">A</button> 
<button onclick="methodB()">B</button> 
<button onclick="methodC()">C</button> 
<button onclick="methodD()">D</button> 
<button onclick="methodE()">E</button> 
+0

這段代碼的性能特徵的非常好的總結 - 以及過度依賴這些代碼的無用性! – 2012-02-10 23:37:40