63

在 Douglas Crockford 所著的Javascript: The Good Parts一书中,作者对 continue 语句的看法如下:

continue语句跳转到循环的顶部。我从未见过没有通过重构删除continue语句来改进的代码。

这真的让我很困惑。我知道 Crockford 对 JavaScript 有一些非常固执的观点,但这对我来说听起来完全错误。

首先,continue不仅仅是跳到循环的顶部。默认情况下,它还会进行到下一次迭代。那么,克罗克福德的声明不只是完全错误的信息吗?

更重要的是,我不完全明白为什么continue甚至会被认为是坏的。这篇文章提供了似乎是一般假设: 为什么在循环内继续是一个坏主意?

尽管我了解continue在某些情况下可能会使代码难以阅读,但我认为它可能会使代码更具可读性。例如:

var someArray=['blah',5,'stuff',7];
for(var i=0;i<someArray.length;i++){
    if(typeof someArray[i]==='number'){
        for(var j=0;j<someArray[i];j++){
            console.log(j);
        }
    }
}

这可以重构为:

var someArray=['blah',5,'stuff',7];
for(var i=0;i<someArray.length;i++){
    if(typeof someArray[i]!=='number'){
        continue;
    }
    for(var j=0;j<someArray[i];j++){
        console.log(j);
    }
}

continue在这个特定示例中并不是特别有益,但它确实证明了它减少了嵌套深度的事实。在更复杂的代码中,这可能会增加可读性。

Crockford 没有解释为什么continue不应该被使用,那么我错过的这个观点背后是否有更深层次的意义?

4

6 回答 6

72

这种说法很荒谬。continue可以被滥用,但它通常有助于提高可读性。

典型用途:

for (somecondition)
{
    if (!firsttest) continue;

    some_provisional_work_that_is_almost_always_needed();

    if (!further_tests()) continue;

    do_expensive_operation();
}

目标是避免“烤宽面条”代码,其中您有深度嵌套的条件。

编辑添加:

是的,这最终是主观的。这是我的决定指标。

上次编辑了一个:

当然,这个例子太简单了,你总是可以用函数调用替换嵌套条件。但是随后您可能必须通过引用将数据传递到嵌套函数中,这可能会产生重构问题,至少与您试图避免的问题一样糟糕。

于 2012-07-30T20:04:30.083 回答
8

我个人与这里的大多数人不同。问题通常不在于显示的continue模式,而在于更深的嵌套模式,可能的代码路径可能变得难以看到。

但是,continue在我看来,即使是你的例子也没有显示出改进是合理的。根据我的经验,一些continue语句是以后重构的噩梦(即使对于像 Java 这样更适合自动重构的静态语言,尤其是后来有人也放在那里的时候break)。

因此,我会在您给出的报价中添加评论:

重构以删除continue语句会提高您进一步重构的能力。

内部循环非常适合用于提取功能。当内部循环变得复杂并continue可能使其变得痛苦时,就会进行这种重构。

这些是我在团队中专业从事 JavaScript 项目工作后的诚实意见,Douglas Crockford 谈到的规则确实显示了它们的优点。

于 2012-07-30T21:53:55.247 回答
7

Douglas Crockford 可能有这种感觉,因为他不相信条件式中的赋值。事实上,他的程序 JSlint 甚至不允许你这样做,尽管 Javascript 可以。他永远不会写:

示例 1

while (rec = getrec())
{   
    if (condition1(rec))
        continue;

    doSomething(rec);
}

但是,我猜他写这样的东西:

示例 2

rec = getrec();

while (rec)
{   
    if (!condition(rec))
        doSomething(rec);

    rec = getrec();
}

这两种方法都有效,但如果你不小心混合了这些风格,你会得到一个无限循环:

示例 3

rec = getrec();

while (rec)
{   
    if (condition1(rec))
        continue;

    rec = getrec();
}

这可能是他不喜欢继续的部分原因。

于 2014-07-27T01:10:44.677 回答
2

Continue 是一个非常有用的工具,可以节省算法中的计算周期。当然,它可能会被不当使用,但其他关键字或方法也是如此。在追求性能时,使用条件语句对路径分歧采取逆向方法可能很有用。continue 可以通过允许在可能的情况下跳过效率较低的路径来促进逆向。

于 2012-07-30T20:14:03.740 回答
2

实际上,从所有分析看来:

  1. 如果您有浅循环 - 如果它提高了可读性,请随意使用 continue (另外,可能会有一些性能提升?)。
  2. 如果你有很深的嵌套循环(这意味着你在重构时已经有一个毛球要解开),从代码可靠性的角度来看,避免 continue 可能会被证明是有益的。

在为 Douglas Crokford 辩护时,我觉得他的建议倾向于防御性编程,老实说,这似乎是在企业中“防止白痴”代码的好方法。

于 2015-05-04T09:19:34.503 回答
1

就个人而言,我从未听说过使用 continue 语句有什么不好的地方。确实可以(大多数时候)很容易地避免使用它,但没有理由使用它。我发现使用 continue 语句可以使循环看起来更清晰,可读性更高。

于 2012-07-30T20:07:16.493 回答