【问题标题】:Speed and memory benefit from declaring variable outside JavaScript loop?在 JavaScript 循环之外声明变量对速度和内存有好处吗?
【发布时间】:2023-03-08 15:08:01
【问题描述】:

C# 也有类似的问题,但我们没有看到 JavaScript 的任何问题。

在循环中声明变量是否被接受?

假设一个循环有 200 次迭代。

使用样本 2 而非样本 1 是否有性能要求(内存和速度)?我们使用 jQuery 来循环。它提高了我们将 var 保留在循环内的代码可读性,但如果这不是最佳实践,或者会导致性能显着降低或内存使用量增加,我们将进行切换。

**Sample 1:**
$(this).each( function() {
   var i = $(some_div).clone();
   *** edit i ***
   $(another_div).append( i );
});



**Sample 2:**
var i = null;
*** edit i ***
$(this).each( function() {
   i = $(some_div).clone();
   $(another_div).append( i );
});

【问题讨论】:

  • @Crashalot:在示例 1 中,每次迭代都会创建变量。在示例 2 中,变量被重用。你做过一些性能测试吗?
  • 不,我们很想知道最佳实践,因为这一定是一种既定模式。我们假设因为 var 被重用,所以性能有所提高,但想知道是否有显着的优势。如果 vars 在循环内部,则代码更容易阅读,但如果速度和内存性能需要在外部声明,那么我们会这样做。
  • 每个实现都可能不同。据您所知,无需进一步研究,任何给定的解释器都可以即时优化它并消除任何惩罚。
  • 一个词法范围查找与非封闭变量。我想这种差异可以忽略不计,并且在浏览器之间会有很大差异。可能不值得理论上的性能提升。写出有意义的东西。
  • 你的两个样本不等价。

标签: javascript jquery


【解决方案1】:

示例 1(内部变量)更快: http://jsperf.com/variable-outside-faster

但差异并不值得关心。

【讨论】:

  • 我们很困惑。里面怎么更快?它不是在执行额外的操作(声明变量)吗?我们也很好奇它对记忆的影响。
  • 嘿,你比我更快地创造了这个。查看this article 中的“Shorten Scope Chains”以获得解释。
  • 声明变量不是额外的操作。例如,Chrome 会在执行之前将该 JavaScript 编译为本机代码。这意味着它将为函数预先分配一些内存。我相信当它尝试解析变量名时,将它放在同一范围内会加快查找速度,因此第一个代码最终会更快。但这只是我的猜测。无论如何,在其他实现中不一定如此,无论是其他浏览器还是嵌入在其他环境(JVM、.NET CLI 等)中的 JavaScript。
  • 在示例 I 中完全取消 i 也是一个微不足道的优化 --- 它可以直接将其传递给 $(...).append 调用
  • 如果有的话,这些测试表明 jsperf 根本不可信。结果应该是相同的,因为测试中实际完成的工作完全影响了 nano 优化,例如变量声明。 -1 对于您和所有认为这可以证明任何事情的人
【解决方案2】:

这是一个微优化,别这样了。

而是将精力投入到编写可读代码以及为代码编写文档和测试上。

但是,有一些高级问题值得优化:

  • 删除像 jQuery 这样让你慢一个数量级的臃肿抽象。
  • 减少您在屏幕上进行的渲染和绘图量
  • 降低算法的大 O 复杂度
  • 减少服务器-客户端行程的延迟。

【讨论】:

  • 如果不是 jquery,你对移动 safari 有什么推荐?
  • 移动是一个资源受限的环境。在某些应用程序中,性能很重要。您没有足够的信息表明不需要这样做。
  • @Crashalot 你不需要库,你使用“vanilla javascript”
  • -1 建议专注于可读代码并建议在同一线程中将 jQuery 替换为 vanilla JS
  • @Raynos 如果有人可以编写跨浏览器 JS,而无需进行数十次功能/浏览器检测测试和/或重新实现大部分 jQuery,这比使用 jQuery 实现的相同功能更清晰,我会印象深刻.浏览器兼容性是导致 vanilla JS 丑陋以及 DOM 接口丑陋的重要原因。编写能够读取您如何做某事的普通 JS 很容易,但将其读取为对您获得的结果的描述要困难得多。 jQuery 在 IMO 中做得相当好。
【解决方案3】:

这将取决于实施,但原则上我认为性能不会有任何明显差异。由于您使用 jQuery 循环,i 变量将在第一种情况下位于函数范围内,而在第二种情况下位于外部范围内。这对内存分配的影响可能略有不同,但我怀疑它是否会引起注意。确保它选择实现并尝试衡量其中性能的唯一方法。

【讨论】:

    【解决方案4】:

    这些在语义上可能不同,所以这是一个苹果与橘子的比较: 例如如果您在 ajax 回调中使用 i 而不是同步使用,那么您几乎可以肯定会多次使用对 i 的最后赋值,而不是在进行此更改时使用每个不同的值。

    纯属猜测:

    因此,我们知道,如果您充分利用 var 内部形式的潜力,您将需要为每个 i 提供不同的内存地址,那么它必须做更多的工作。

    需要大量分析才能确定$.each 同步使用它的回调参数。因此,如果这是一个有效的优化,我怀疑大多数 JS 编译器将无法做到这一点,而手工制作应该会给你(恒定时间)速度和内存改进。

    其他注意事项:

    更多的词法范围可能意味着查找变量的成本线性增加。

    【讨论】:

      猜你喜欢
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 2011-04-10
      • 1970-01-01
      • 2014-06-15
      • 2020-07-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多