2014-02-21 67 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(正确):) –