2011-08-24 217 views
54

通过jQuery的源我偶然发现了下面这段代码阅读(可here):For循环代替while循环

for (; i < length;) { 
    if (callback.apply(object[i++], args) === false) { 
     break; 
    } 
} 

为什么在这里用来代替while环路for循环?

+6

我不知道这个代码在最小化时是否更短?这是可怕的代码,而jQuery的人都是聪明人,所以我认为这是为了缩小目的。 –

+9

删除所有空格,@ aroth的版本更短。可以缩短的任何变量名称的使用次数相同。可以变得更短。 'while(i user113716

+0

有人可能会争辩说,在缩小代码中用这种形式替换所有while循环会更好地压缩。不过,不知道这是不是他们想到的。 –

回答

44

我投票赞成有不良编码风格的人。这是我可以看到for循环和i++放在数组下标中的唯一解释。我认为这将是更好的:

while (i < length && callback.apply(object[i], args)) { 
    i++; 
} 

或者,如果你碰巧觉得===运营商在最初的例子具有价值,那么:

while (i < length && callback.apply(object[i], args) !== false) { 
    i++; 
} 

这样做的另一个可能的原因可能是因为性能优化。虽然我整理的这个快速的benchmark似乎反驳了那个理论。在Windows上,while循环比Chrome中的原始for循环快20%,在IE和Firefox两个循环中执行相同。在OS X上,for循环在Firefox中占有10%的优势,两者在Chrome中没有区别,Safari浏览器喜欢while循环6%。

所以从性能的角度来看它是一种洗涤。如果有的话,然后根据市场份额来判断,在Mac上针对Firefox进行优化之前,您可能希望针对Windows优化Chrome,在这种情况下,首选while循环。

对我来说,性能优化不太可能影响这个代码。然后我回到我的原始理论,这只是一个糟糕的编码风格,使其超过代码审查过程的一个例子。

+4

严格的'false'测试是必要的,因为这是* one *返回值将会破坏迭代。 – user113716

+0

在我的例子中,我不会“1”吗? – AnteSim

+0

如果回调可能返回'undefined'或'0',则需要第二个版本才能与原始版本保持一致。在这些情况下,第一个版本不会起到相同的作用。 – jfriend00

2

我发现这样的事情发生在我重写东西或多人触摸一段代码时。看不到任何特定的原因。

我希望得到正确的初始化此块以上。

6

首先,是从来没有使用一个for循环在while环路长度的成本,但你得到与for环附加的功能,所以一些程序员只是一直使用for

for(;<condition>;){} 
while(<condition>){} 

这么说,我觉得这里的目的可能是与周围代码的一致性。

例如,这里是原始代码的一部分。正如你所看到的,在此代码,你可以留在思考整个时间的“for”循环模式,所以它感觉更加一致:

if (args) { 
    if (isObj) { 
     for (name in object) { 
      if (callback.apply(object[name], args) === false) { 
       break; 
      } 
     } 
    } else { 
     for (; i < length;) { 
      if (callback.apply(object[i++], args) === false) { 
       break; 
      } 
     } 
    } 
} 

与此相比,具有while替换第二循环。当你阅读这段代码时,你必须从“for”循环模式转换到“while”循环模式。现在我不知道你的情况,但是我发现在上面的循环条件之间进行切换,而不是在下面的循环条件下,我的眼睛稍微快一点。这是因为,在上述情况下,我可以把心思放在了条件,而在以下情况下,我的目光都吸引了whilefor每一次,因为它们是不同的重读:

if (args) { 
    if (isObj) { 
     for (name in object) { 
      if (callback.apply(object[name], args) === false) { 
       break; 
      } 
     } 
    } else { 
     while (i < length) { 
      if (callback.apply(object[i++], args) === false) { 
       break; 
      } 
     } 
    } 
} 
0

最短和最诚实的答案很短“只是因为”。 这样做绝对没有实际的理由,我们不从这样的2微笑循环中获得任何收益。

至于上述原因,如:

  • 重构 - 这是最有可能的,但尽管如此,这不是借口。
  • 小型化的考虑 - 这是少一点,较少可能。
  • 心理/可读性/代码支持问题 - 我非常怀疑有人写这样的代码记住用户可能会因为代码构造和松散集中而感到困惑;

好吧,至于这些原因 - 他们都绝对值得一提,但说实话,jquery代码风格并不理想。有时候的原因,有时候,这只是一个事实问题。

生产代码并不总是最漂亮的代码。阅读任何语言的生产就绪,硬核代码总是很好,但不是100%的代码风格。说,vim是美丽的,非常强大的软件,但(对我来说)一些纯粹主义者可以对它的源代码感到惊讶。虽然循环的东西是好的))))

21

这里是the commit that introduced this oddity。在$.each$.curCSS减少代码:

提交消息:

jquery的核心。从DIFF

剪断:

-  for (var i = 0, length = object.length; i < length; i++) 
-   if (callback.apply(object[ i ], args) === false) 
+  for (; i < length;) 
+   if (callback.apply(object[ i++ ], args) === false) 

这样看来,笔者简单地错过了改变forwhile的机会。

+0

不错的电话。这似乎是最可能的答案。 – wprl

0

所以t至少运行一次,因为如果你使用while循环,如果逻辑是假的,它不会运行。即使它是假的,它也会运行至少一次。