为什么封装的Javascript函数有这么大的性能差异?

时间:2013-12-03 15:12:38

标签: javascript performance optimization compiler-construction v8

所以我有这个简单的代码:

function Run () {
  var n = 2*1e7;
  var inside = 0;
  while (n--) {
    if (Math.pow(Math.random(), 2) +
        Math.pow(Math.random(), 2) < 1)
      inside++;
  }

  return inside;
}

var start = Date.now();
Run();
console.log(Date.now() - start);

它会在335毫秒左右输出一些时间。那很不错。但是,如果我像这样封装Run函数:

var d = Date.now();
(function Run () {
  var n = 2*1e7;
  var inside = 0;
  while (n--) {
    if (Math.pow(Math.random(), 2) +
        Math.pow(Math.random(), 2) < 1)
      inside++;
  }

  return inside;
})();
console.log(Date.now() - d);

它将输出18319ms,这比以前的情况要糟糕得多。这是为什么?

另外,如果重要的话,我在控制台的Chrome 26.0.1410.63上运行它。在node.js上,两个片段在控制台上都表现良好。

1 个答案:

答案 0 :(得分:3)

函数解除和函数表达式WRT与优化没有区别,这将是荒谬的。


Google Chrome中的控制台代码包含在with语句中,如下所示:

 with ((console && console._commandLineAPI) || {}) {
      //Your code is concatenated here
 }

因为函数声明被提升,所以前面的代码实际上是这样的:

function Run () {
  var n = 2*1e7;
  var inside = 0;
  while (n--) {
    if (Math.pow(Math.random(), 2) +
        Math.pow(Math.random(), 2) < 1)
      inside++;
  }

  return inside;
}

with ((console && console._commandLineAPI) || {}) {
  var start = Date.now();
  Run();
  console.log(Date.now() - start);
}

因此声明正在外部 with声明中运行。实际上,在块function declaration can only be a top level statement中使用函数声明是无效的语法。

所以无论如何,由于历史原因,V8很好并且提升它而不是抛出语法错误:

var i = 3;

with({i:4}) {
    function test() {
        console.log(i);
    }
}
test();//logs 3 so it is obviously **not** under `with` influence

因为声明不在with语句下,所以它运行得更快。声明在V8下不可优化*也会打破词法范围。


*不可优化意味着优化编译器不会查看代码,只有通用编译器才会为函数生成代码。它与firefox的解释器和JIT模式相当。如果您想进一步了解V8中禁用优化的语言功能,请阅读optimization killers