2014-02-21 64 views
2

當分配給一個函數聲明的變量,並分配給上範圍內的變量時,我對執行速度的顯着差異有點困惑。Javascript範圍訪問性能 - 25倍慢?

我已經寫了一個小措施功能,我一直對這類事情在全球範圍內,這裏的一些結果:

鉻(控制檯)

measure("assignment to var in current scope", function(){ 
    var i = 1; 
    (function(){})(i) 
}) 
15:52:49 |INFO| Measure 'assignment to var in current scope' performed 76236944 operations per second 
iterations: 10000000 duration: 141 totalcalllag: 9.83 

...和上部範圍

var i = 0; 
measure("assignment to var in upper scope", function(){ 
    i = 1; 
    (function(){})(i) 
}) 
15:53:22 |INFO| Measure 'assignment to var in upper scope' performed 2935124 operations per second 
iterations: 10000000 duration: 3417 totalcalllag: 9.99 

即用於分配操作/秒範圍相比3百萬 ops/sec在上範圍內的分配比例爲〜1:25


IE11(控制檯)

measure("assignment to var in current scope", function(){ 
    var i = 1; 
    (function(){})(i) 
}) 
15:54:14|INFO| Measure 'assignment to var in current scope' performed 46038396 operations per second 
iterations: 10000000 duration: 247 totalcalllag: 29.790000000000002 

var i = 0; 
measure("assignment to var in upper scope", function(){ 
    i = 1; 
    (function(){})(i)}) 
8669267 
15:54:49 |INFO| Measure 'assignment to var in upper scope' performed 8669267 operations per second 
iterations: 10000000 duration: 1183 totalcalllag: 29.5 

這裏我們看到而不是每秒 OPS。


測量功能

var measure = function (desc, f) { 

    // measure the calling code first 
    var start, stop, callLag, nothing = function() { 
    }; 
    var iterations = 0; 
    var COUNT = 1000; 
    var duration = 0; 
    while (duration < 10) { 
     COUNT *= 1000; 
     start = (new Date()).getTime(); 
     while (iterations != COUNT) { 
      ++iterations; 
      nothing(); 
     } 
     stop = (new Date()).getTime(); 
     duration = stop - start; 
    } 
    callLag = duration/COUNT; 

    // measure for total time between 0.1 & 10 seconds 
    iterations = 0; 
    COUNT = 1000; 
    duration = 0; 
    while (duration < 100) { 
     COUNT *= 100; 
     start = (new Date()).getTime(); 
     while (iterations != COUNT) { 
      ++iterations; 
      f(); 
     } 
     stop = (new Date()).getTime(); 
     duration = stop - start; 
    } 

    // calculate operations per second 
    var opsPerSec = Math.floor(1000 * (iterations/(duration - (callLag * iterations)))); 

    Log.info("Measure '" + desc + "' performed " + opsPerSec.toString() + " operations per second\n" + 
     "\titerations: " + iterations + "\tduration: " + duration + "\ttotalcalllag: " + callLag*iterations); 

    return opsPerSec; 
}; 

問題

我將做一些重號很快與JavaScript的運算。這種行爲在所有瀏覽器中是否一致?我是否應該考慮實現這些功能?我是否應該將參數傳遞給函數以避免在較高範圍內訪問它們?

......還是我錯過了什麼?

+0

這可能是不回答你正在尋找,但JavaScript是不是大數量計算的最佳選擇。如果有其他替代方案可用,您最好使用它們。 (有時你別無選擇,只能使用JavaScript,但這取決於這是否是其中的一種)。 –

+0

它主要用於在線字符識別 - 在瀏覽器中。 –

回答

0

理論上它不應該在JavaScript中有任何區別。變量聲明在JavaScript中非常重要,因爲語言只有function scope(與塊範圍相反)。我始終遵循JavaScript大師Douglas Crockford(Javascript:The Good Parts的作者)的建議。

JavaScript does not have block scope, so defining variables in blocks can confuse programmers who are experienced with other C family languages. Define all variables at the top of the function.

請閱讀更多細節:Variable Declarations

我也建議使用Crockford的JSLint: The JavaScript Code Quality Tool他還提出警告:JSLint will hurt your feelings

+0

我嘗試過採用這個建議,但是至少在javascript中我發現我的代碼更具可讀性/可維護性,如果我只是聲明最接近它們使用位置的變量。它不會影響性能。 查找變量的範圍會有性能問題,但它不應該是這個巨大的!也許所有當前的作用域變量都保存在CPU緩存中?我不知道。 –

+1

我也一直在想。 CPU緩存將是訪問它們的最快方式,因此在其他範圍內查找變量的成本更低。另請參閱OReilly的「編寫高效的JavaScript:第7章」:http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html – HackerKarma

+0

+ 1 。尼古拉斯確實知道他的東西。我第一次從他的書中學到JavaScript(正確):) –