【问题标题】:In a loop, do any operations in the end-condition get evaluated in every iteration?在循环中,结束条件中的任何操作是否在每次迭代中都得到评估?
【发布时间】:2010-10-13 20:55:52
【问题描述】:

在以下代码中:

for (var i = 0; i < object.length; i++){  
    ....  
}  

操作object.length 在迭代中每次都会被评估吗?
语言将评估一次并保存结果是最有意义的。但是,我正在阅读一些代码,其中有人在循环开始之前评估了操作并将其存储在结束条件中使用的变量中。
不同的语言有不同的处理方式吗? Javascript 的任何具体信息?

【问题讨论】:

    标签: javascript for-loop


    【解决方案1】:

    这显然取决于语言。对于 JavaScript,规范(ECMAScript §12.6.3)要求每次都对其进行评估。作为一种优化,一个特定的 JavaScript 运行时可以跳过一个或多个长度调用,如果它可以证明结果不会改变的话。

    【讨论】:

      【解决方案2】:

      完全取决于语言和(可能)循环中的内容。编译器/解释器可能无法确定“长度”属性不会被循环中的某些内容更改。

      在 Javascript 中,可以肯定的是它会被重新评估。像这样的简单属性引用可能还不错,但是像函数调用这样的东西可能是性能问题。 edit为了澄清,我所说的“函数调用”是指任何形式的代码,它以任何方式计算循环终止条件的成本足以让你在每次迭代时都感觉不好。

      因此(请原谅我的 jQuery),

      for (var i = 0; i < $('.foo').length; ++i) { /* ... */ }
      

      每次迭代都会涉及到整个 DOM 的遍历。

      【讨论】:

      • 函数调用本身与动态语言中的性能问题没有直接关系;例如,函数体可以内联。
      • “简单的属性引用”可能会调用复杂的 getter 函数(尽管在这种情况下应该很简单)。
      • @Chris - 哦,是的;我应该说的是“做很多工作的函数调用”。我可以澄清一下。
      • 另一个例子(使用提示而不是 jQuery): for (var i=0; i
      • 您可以向后迭代 - 请参阅下面的答案。
      【解决方案3】:

      必须在循环的每次迭代中重新评估条件,因为理论上值可能在循环体内发生了变化。

      【讨论】:

        【解决方案4】:

        智能编译器可以自动针对这种情况进行优化,但是在 JavaScript 中执行静态分析以确定循环内的长度不会改变是极其困难的。出于这个原因,您可以说在大多数情况下,object.length 确实会在每次迭代中重新评估。

        另一方面,程序员通常更容易推断出长度肯定不会改变,如果你真的(我的意思是,真的)担心性能,你可以在循环开始之前预先计算并存储长度。

        【讨论】:

          【解决方案5】:

          如果顺序对您不重要,请向后迭代。在这种情况下,您不需要保存长度的凌乱临时变量。循环的 start 条件只被评估一次(显然,一旦循环已经开始,重新评估它是没有意义的!)。使用早期响应中的示例:

          for (var i = $('.foo').length - 1; i >= 0; i--) { /* ... */ }
          

          我知道我在被问到很久之后才回答这个问题,但它在相关查询的 Google 搜索结果中仍然显示很高,而且现有答案似乎都没有暗示这种替代方法。

          【讨论】:

          • for (var i = $('.foo').length; i --&gt; 0;) { /* ... */ } 以获得额外的互联网积分。 ;)
          【解决方案6】:

          在某些语言中,这取决于您在构建时配置的优化级别。例如,我相信 C++,将字段标记为 volatile 将强制重新评估。查看这些链接:

          http://en.wikipedia.org/wiki/Loop_unwinding

          http://msdn.microsoft.com/en-us/library/12a04hfd.aspx

          【讨论】:

            【解决方案7】:

            在 Javascript 中,它每次都会被评估。你可以通过在循环的第一部分设置一个“max”变量来绕过它:

            for (var i=0, imax=object.length; i<imax; i++) {
              // statements
            }
            

            【讨论】:

              【解决方案8】:

              是的,每次迭代都会计算出来..

              为什么不测试呢?

              var loop = 5;
              
              for (var i = 0; i< loop; i++)
                  {
                  alert(i + ' of ' + loop);
                  loop--;
                  }
              

              住在http://jsfiddle.net/MSAdF/

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2014-06-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-11-20
                相关资源
                最近更新 更多