ES6 JavaScript - const inside 还是 let outside 循环?

Posted

技术标签:

【中文标题】ES6 JavaScript - const inside 还是 let outside 循环?【英文标题】:ES6 JavaScript - const inside or let outside loop? 【发布时间】:2018-11-21 07:25:52 【问题描述】:

出于性能目的,我想知道 ES6 javascript 之间有什么区别:

var list = [...];
let item; //let outside the loop
for (let i = 0; i < list.length; i++) 
    item = list[i];

var list = [...];
for (let i = 0; i < list.length; i++) 
    const item = list[i]; //const inside the loop

假设item 变量在循环内保持不变。

有推荐的吗?相对于每个性能的优缺点是什么? GC 处理它们的方式不同吗?

请注意,这是微优化。此外,性能取决于所使用的 JS 引擎。(请参阅答案)

【问题讨论】:

性能很少需要担心,但我认为应该不会有任何显着差异(尽管您可能会考虑测量长度一次,而不是每次迭代)。也就是说,在循环中使用const 无疑是提高可读性的最佳选择。 Premature optimization is the root of all evil @Barmar 这不是过早的优化。我已经编写了代码,调试了它等等。现在我知道它是可靠的,我想最大限度地提高它的效率,因为它在我的程序中大量使用。 @MaxK 您的性能测试是否表明这是一个瓶颈?如果您还没有将其确定为需要调优的地方,那就是过早的优化。 将某些内容标记为常量会产生垃圾收集成本。对象在 VM 中的处理方式不同;分配一个项目然后在每个循环结束时释放它的成本似乎也不合理。尽管在几次迭代中影响可能很小,但这似乎是一种反优化 【参考方案1】:

考虑到不同的浏览器有非常不同的内部实现,很难给出明确的答案。很可能存在零差异。在执行之前,浏览器中的 Javascript 由内部 JIT 编译器编译,它很可能会识别循环内的冗余变量声明并对其进行优化,就像任何其他好的编译器一样。 letconst 肯定会影响这一点,我会说 const 将更有可能在循环外进行优化,因为编译器可以立即看到它是特定于内部循环范围的不可变原子变量。 它也可能会展开性能密集型循环。 Javascript 还有一些其他的性能怪癖,尽管在更高范围内访问变量会导致轻微的性能损失,我记得很久以前在浏览器中执行 gamdev 时研究过这一点。那可能不再是最新的了,但那是几年前的事了。

正如其他人所指出的,除非分析已经表明这是您的应用程序中的一个严重瓶颈,否则它是过早的优化。如果优化它可能会带来任何显着的性能优势,我会感到非常震惊。如果这方面的性能很重要,最好的建议是自己分析不同的场景并确定最适合您的用例。

【讨论】:

I'd say const would make optimisation out of the loop even more likely considering the compiler can instantly see that it's an immutable atomic variable specific to the inner loop scope 你确定吗?出于某种原因,我认为您可以在循环块中重新声明 const 的原因与它不能像变量重新分配一样进行优化的原因相同。 这都是猜测,没有经过实际测试,但我想说如果你分配const item = list[i];,JIT 编译器很可能会看到它是一个原子常量变量,直到超出范围并被垃圾收集。它可能会检查对list[i] 的修改,如果没有,它可能会优化整个步骤并直接引用list[i]。这就是大多数编译器的处理方式。 这是有道理的。 list 的值是否会影响编译(例如,list = ['one', 1, , Array(5), function()])? 我陷入了困境,重温了有关字节码和涡轮风扇的旧文章:P 如果以后有时间,我会尝试研究 V8 的作用。 绝对!它必须编译您打算在变量上使用的代码,如果它们是同质类型,它肯定可以创建更优化的代码。再次,猜想。但这似乎与我们已经知道的信息一致。 blog.ghaiklor.com/how-v8-optimises-javascript-code-a0f3bbd46ac9【参考方案2】:

在第一个示例中,item 的范围位于循环之外,因此分配的最终值将在任何封闭范围内可用。在后一个示例中,item 在循环关闭后未定义。您也无法在循环内重新分配 item,因为它是 const 而不是 let

就个人而言,我会使用第二个,除非有理由使用第一个。由于对变量分配的额外需求,性能差异将是最小的,但对于第二个示例稍微更差。

【讨论】:

【参考方案3】:

免责声明:我现在认为以下内容是猜想,并且会犹豫是否建议将其选作答案,直到可以确认为止。在那之前,我会把它放在这里以供 cmets 和确认;如果发现不正确,将被删除。


有两点需要考虑:

    letconst 循环内的变量声明

两者都依赖于浏览器的实现,因此性能并不是一成不变的;但是,通常第一个(在循环外声明 let)应该会产生更有效的结果,因为声明变量通常比单独赋值需要更多的 OPS。

需要注意的是,结果的效率会受到几个因素的影响。这些包括但不限于:

用于执行代码的系统资源 执行的操作类型(如果与初始示例不同) 列表的长度及其值的大小

虽然很难确定代码的效率会提高多少,但重要的是要注意在平均条件下(平均多核桌面 w/至少 2GB 内存)具有平均大小的列表(例如 5k元素),结果的差异将是纳秒到微秒,考虑到这种差异通常被认为是微优化。

【讨论】:

当你说更有效的结果时,如果你能提到效率多少,例如以毫秒为单位,这将有所帮助。因为在大多数情况下,可读性将赢得微优化。 @Fabio 谢谢,我会尝试更新并进行编辑以进行澄清 你确定吗?请记住,浏览器中的Javascript 编译的,任何体面的编译器都应该能够识别冗余变量声明。我很确定无论哪种方式,您最终都会得到非常相似的生成字节码。 @ajxs 你是对的。对于字节码,const 可能会更快,因为它会预编译资产。我很犹豫是否建议这样做,但我认为根据旧信息,let 被确定为更有效率,var 比它更多。不过,我可能会删除这个答案,因为它对实施非常重要 一般来说,NodeJS(不是微软的 ChackraCore)运行 V8 并且可以用来分析性能。

以上是关于ES6 JavaScript - const inside 还是 let outside 循环?的主要内容,如果未能解决你的问题,请参考以下文章

ES6 JavaScript - const inside 还是 let outside 循环?

JavaScript ES6 - let 与 const 使用方及与var对比

JavaScript ES6 - let 与 const 使用方及与var对比

javascript ES6简介 - 比较Var - to Let和Const

Javascript ES6 如何将 const 函数转换为函数

JavaScript学习笔记 -- ES6学习 let 和const