从自执行函数返回函数的Javascript性能是什么?

时间:2012-08-24 13:20:22

标签: javascript performance scope

在firefox中,以下两个函数之间似乎存在很大的性能差异:

var n1 = 12;

var add1 = function(n2){
    return n1 + n2;
}

var add2 = (function(){
    return function(n2){
            return n1 + n2;
    }
})();

我认为这必须归结为另一个范围的引入,因此创建了第三个示例,其中变量缓存了一个级别。 但这显示出更大的减少(80%!)

var add3 = (function(){
    var cn1 = n1;
    return function(n2){
            return cn1 + n2;
    }
})();

我原以为这里的关闭会缩小性能差距,而不是扩大性能差距。有没有人知道这里发生了什么?

jsPerf测试页:http://jsperf.com/variable-scope-speed

2 个答案:

答案 0 :(得分:2)

它有趣,但我在这里的小测试似乎证实了我之前的假设,即 jsPerf 环境影响范围和范围链查找本身。我没有深入研究“如何”和“为什么”,但这是我的小试物:

var n1 = 12;

var add1 = function(n2){
        return n1 + n2;
}

var add2 = (function(){
        return function(n2){
                return n1 + n2;
        }
})();

var add3 = (function(){
        var cn1 = n1;
        return function(n2){
                return cn1 + n2;
        }
})();

var add4 = function( n2, n1 ) {
    return n2 + n1;
}.bind(null, n1);


var tests = [add1, add2, add3, add4],
    start, stop, loops;

tests.forEach(function( fnc ) {
    loops = 100000;

    start = Date.now();
    while( loops-- ) {
        fnc( 2 );
    }
    stop = Date.now();

    console.info('Method ', fnc.name || fnc.toString(), ': ', stop - start, ' ms.');
});

我的FireFox 14上的结果如下:

  

方法add1:570ms   方法add2:566ms   方法add3:414ms   方法add4:479ms。

最新Chrome结果:

  

方法add1:199ms   方法add2:136ms   方法add3:85ms   方法add4:144ms。

这看起来更合理。封闭的范围链查找必须总是更快,只是因为查找链更短。即使所有现代浏览器通常都不进行经典范围链查找,我也知道这一点。无论如何,由于浏览器为免费(或超出范围)的变量创建了非常聪明的查找表,所有结果至少应该相同。过度优化全局对象访问IMO没有任何意义。

正如您所注意到的,我为绑定方法创建了一个额外的测试用例。

答案 1 :(得分:0)

var n1 = 12;

// "add1" is superfast in Firefox, but not in Chrome. Why?
// it seems Firefox is smarter in retrieving n1 value from global scope
var add1 = function(n2){
        return n1 + n2;
}

// "add2" is much slower in Firefox, but in Chrome the speed is almost equal to "add2"
// it seems that Firefox's smart retrieving from global scope is not applied in this case
// it is understandable that "add2" is slower, because the interpreter needs to go back two levels in the scope chain to find the "n1" variable value
var add2 = (function(){
        return function(n2){
                return n1 + n2;
        }
})();

// If JavaScript works as PHP, then it won't copy "n1" value in "cn1".
// If this is the case, then it is understandle why it is slower.
// The interpreter first needs to search and find "cn1" value;
// when it finally finds it in the previous scope level,
// then it needs to start a second "search and find travel", looking for the value.
// This means "cn1" does not contain "12", but a reference to it in the memory.
// While I don't know if this is how JavaScript engine works,
// I know that PHP does not create a copy of the value -
// both variables share the same content in the memory.
// Short story being: it is slower because it must perform two "searches" instead of one.
var add3 = (function(){
        var cn1 = n1;
        return function(n2){
                return cn1 + n2;
        }
})();