在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
答案 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;
}
})();