【问题标题】:Why are "continue" statements bad in JavaScript? [closed]为什么 JavaScript 中的“继续”语句不好? [关闭]
【发布时间】:2012-07-28 13:11:09
【问题描述】:

在 Douglas Crockford 的 Javascript: The Good Parts 一书中,这就是作者对 continue 语句要说的全部内容:

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

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

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

更重要的是,我不完全理解为什么continue 甚至会被认为是坏的。这篇文章提供了似乎是一般假设: Why is continue inside a loop a bad idea?

虽然我了解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,那么我错过的这个观点背后是否有更深层次的意义?

【问题讨论】:

  • 关键字continue 是一个工具 - 在适用的情况下使用它。有时它是必要的,大多数时候它不是。唯一不好的时候是你不需要使用它,但是因为太懒或太草率而无法以其他方式使用它。
  • 我也有同样的感觉,这就是我创建post 的原因。对我有帮助的是在使用 continue 语句时只想到 hop 这个词。我认为克劳福德先生在设计语言时在这里使用了一个糟糕的选择词:P 特别是因为 hop 可以应用其背后的逻辑“继续”。如果你跳过某些东西,你通常也会继续。将马拉松田径运动员视为一个很好的类比。
  • “克劳福德先生”并非设计语言。
  • 我对 Crockford 的了解越多,我就越不尊重他的意见。他似乎只是一个脾气暴躁的老看门人,有着完全非理性的品味偏好,他伪装成经验磨练的智慧。
  • @TylerH 我们可以将 Crockford 先生标记为“主要基于意见”吗?大声笑

标签: javascript readability continue


【解决方案1】:

这句话很荒谬。 continue 可以被滥用,但它通常有助于可读性。

典型用途:

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

    some_provisional_work_that_is_almost_always_needed();

    if (!further_tests()) continue;

    do_expensive_operation();
}

我们的目标是避免使用“千层面”代码,在这种代码中,条件句嵌套很深。

编辑添加:

是的,这最终是主观的。 Here's my metric for deciding.

最后一次编辑:

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

【讨论】:

  • 我还要补充一点,可读性是主观的,虽然大多数人似乎喜欢使用 continue,但其他人可能不喜欢。出于同样的原因,人们讨厌 goto,它们本质上并不邪恶(只有滥用 goto 才是邪恶的)。
  • 见我的帖子here。我认为选择这个词是错误的,我认为hop 应该是一个更好的词。但现在为时已晚!
  • 使用continue 还允许以函数式 风格阅读代码,例如:for(a in b) { if (condition1) continue; if (condition2) continue; doSomething(); } 类似于b.filter(condition1).filter(condition2).forEach(a =&gt; ...);
【解决方案2】:

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

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

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

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

内部循环非常适合用于例如提取函数。当内部循环变得复杂时进行这种重构,然后continue 可能会使其变得痛苦。

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

【讨论】:

  • 我不确定我明白你的意思。你介意举个例子说明continue 将成为“重构的噩梦”吗?另外,“提取功能”是什么意思?这是一种设计模式吗?
  • “提取函数”(也可以在“提取方法”下搜索)是一种重构技术,用于将函数体的一部分提取为新的单独函数。即使是此处另一个答案中带有 2 个 continue 语句的简单代码也需要重写(以摆脱 continue 语句),以便从 for 循环的主体中创建一个新函数。当您使用更多嵌套的 continue 语句获得更大的主体时,需要花费大量时间来清理您的代码。
【解决方案3】:

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();
}

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

【讨论】:

  • 你可能说得有道理,但我相信他首先也普遍反对while循环。
  • @twiz:我的观点也适用于for 循环和do 循环。他肯定相信某种循环!
  • rec = getrec(); 出现两次,违反了 Don't Repeat Yourself。
  • @twiz 在他的最新著作中,当他倾向于使用循环而不是(首选)递归函数时,他使用while (true) { ... }
  • @diachedelic 他的最新著作是什么?只是更新版本?
【解决方案4】:

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

【讨论】:

    【解决方案5】:

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

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

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

    【讨论】:

      【解决方案6】:

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

      【讨论】:

      • 确实如此。为了增加您的答案,转译器在内部将等效于 continue 语句添加到生成的程序集中每个循环的末尾。所以现实地说,continue 语句不仅不错,事实上它们实际上非常好。
      猜你喜欢
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-01
      • 1970-01-01
      • 2011-05-23
      • 2015-12-07
      • 2020-08-21
      相关资源
      最近更新 更多