为什么JavaScript中的“继续”语句不好?

时间:2012-07-30 20:03:04

标签: javascript readability continue

在Douglas Crockford撰写的“ Javascript:The Good Parts ”一书中,这是作者对继续声明所说的全部内容:

  

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不应该被使用,所以这个意见背后有一些更深层的意义我错过了吗?

6 个答案:

答案 0 :(得分:68)

这句话太荒谬了。 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.

最后一次编辑:

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

答案 1 :(得分:8)

我个人在另一边,而不是大多数人。问题通常不在于显示的continue模式,而是嵌套更深的模式,可能的代码路径很难看到。

但即使你的一个continue的例子也没有显示出我认为合理的改进。根据我的经验,一些continue语句稍后是噩梦重构(即使对于更适合像Java这样的自动重构的静态语言,尤其是当有人稍后放置break时也是如此)

因此,我会在你给出的引文中加上评论:

  

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

内圈很好地被认可,例如提取功能。当内环变得复杂然后continue可能使它变得痛苦时,就会进行这种重构。

这是我在团队中专业研究JavaScript项目之后的诚实意见,道格拉斯·克罗克福德谈到的有关真正展示其优点的规则。

答案 2 :(得分:5)

道格拉斯·克罗克福德可能会有这种感觉,因为他不相信有条件的任务。事实上,他的程序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();
}

这可能是他不喜欢继续的原因之一。

答案 3 :(得分:2)

Continue是一种非常有用的工具,可以节省算法中的计算周期。当然,它可能被不正确地使用,但其他关键词或方法也是如此。在努力提高性能时,使用条件语句对路径分歧采用逆方法会很有用。继续可以通过允许在可能的情况下跳过效率较低的路径来促进逆转。

答案 4 :(得分:2)

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

  1. 如果你有浅循环 - 随意使用,如果它提高了可读性(同样,可能会有一些性能提升吗?)。
  2. 如果你有深层嵌套循环(这意味着当你重新考虑因素时你已经有一个毛球要解开),从代码可靠性的角度来看,避免继续可能是有益的。
  3. 为了保卫道格拉斯·克罗克福德,我觉得他的建议倾向于倾向于defensive programming,诚然,这似乎是对企业中的代码进行“白痴证明”的好方法。

答案 5 :(得分:1)

就个人而言,我从未听说过使用continue语句有什么不好。确实可以(大部分时间)容易避免,但没有理由使用它。我发现使用continue语句可以使循环更清晰,更具可读性。