for循环中的javascript 'let'和 'var'

标签 javascript performance google-chrome firefox ecmascript-6

在我搜索具体数字以支持在 Javascript 中使用 const 关键字时,我偶然发现了所有三种变量声明类型 var、let 和 const 之间的性能比较。我不喜欢测试设置,所以我创建了 a simplified one .

我没想到会有太大差异,Firefox 达到了我的预期:

jsPerf results on Firefox 52

但是在 Chromium 中发生了一些奇怪的事情:

jsPerf results on Chrome 57

不仅所有测试结果都显着降低,而且 let 循环内部分解为速度的一小部分。

我决定在 Browserstack 中运行测试,以确保它不是我古怪的 Linux 设置。同样的情况也发生在 Windows 10 上的 Firefox 53Chrome 58 上。我什至测试了稍旧的 Chrome 50 并得到了相同的行为。

这是怎么回事?是错误吗?

编辑:一些人评论说循环可能只是被优化掉了,因为它什么都不做。为了表明情况并非如此,我更改了 the test .

最佳答案

当您使用 let 时,for 循环的主体必须创建一个新范围来处理循环变量的正确生命周期,但是在许多情况下,可以优化掉额外的代码和运行时间.例如考虑这段代码:

let sum = 0;
let fns = [];
for (let i=0; i < 1000; i++) {
  function foo() { sum += i; }

  fns.push(foo);

}

当您通过 babeljs 运行它时,您可以看到它生成的等效 ES5 代码包括一个函数调用,以保持正确的变量生命周期:

var sum = 0;
var fns = [];

var _loop = function _loop(i) {
  function foo() {
    sum += i;
  }

  fns.push(foo);
};

for (var i = 0; i < 1000; i++) {
  _loop(i);
}

但是,babel 足够智能,如果您不做任何需要延长循环变量生命周期的事情,它只会使用普通的 for 循环,主体内联。所以你的代码:

for (let i=0; i < 1000; i++) {
  true;
}

可以证明完全等同于:

for (var i=0; i < 1000; i++) {
  true;
}

我的猜测是 Chrome 内部会发生非常相似的事情,但他们还没有优化他们不必保持循环变量事件的情况。

看看我在此示例顶部使用的代码在 Firefox 和 Chrome 中的比较情况会很有趣,因为我怀疑它们最终应该同样慢。您应该注意像空循环这样的计时问题,因为优化对结果的影响可能远远超过实际代码的正常情况。

关于for循环中的javascript 'let'和 'var',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43847863/

相关文章:

javascript - Angular, Material 形式只说提交尝试后需要字段

sql - 为什么这个 MySQL 更新会永远持续?

safari - Facebook Connect按钮未显示在Safari/Chrome中

css - 如何设置元素的:hover state in Chrome dev tools and edit child's style

c# - 高性能的属性访问和可能的动态编译

javascript - 谷歌浏览器扩展程序 : Cannot launch Print dialog

javascript - LinkedIn 分享按钮不抓取图像或分享内容

javascript - 使用 javascript 警报框在 php 中连接字符串

javascript - jslint 错误的属性名称 '$wrapper'

java - App 的背景音乐应该有自己的主线吗?