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

twi*_*wiz 62 javascript readability continue

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

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这可以重构为:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

continue在这个具体的例子中并不是特别有益,但它确实证明了它减少了嵌套深度的事实.在更复杂的代码中,这可能会提高可读性.

Crockford没有解释为什么continue不应该使用,所以这个意见背后有一些更深层次的意义,我错过了吗?

egr*_*nin 72

这句话太荒谬了.continue可以被滥用,但它往往有助于提高可读性.

典型用途:

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

    some_provisional_work_that_is_almost_always_needed();

    if (!further_tests()) continue;

    do_expensive_operation();
}
Run Code Online (Sandbox Code Playgroud)

目标是避免"烤宽面条"代码,你有深度嵌套的条件.

编辑添加:

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

最后一次编辑:

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


jJ'*_*jJ' 8

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

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

因此,我会在您给出的引用中添加注释:

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

并且内部循环非常适合例如提取功能.当内环变得复杂然后continue可能使其痛苦时,进行这种重构.

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

  • 我不确定我知道你的意思.您是否介绍一下"继续"将成为"重构噩梦"的例子?另外,"提取功能"是什么意思?这是一种设计模式吗? (5认同)
  • "提取函数"(也可以在"提取方法"下用Google搜索)是一种重构技术,用于将函数体的一部分提取到一个新的单独函数.即使是另一个带有2个continue语句的另一个回答中的简单代码也需要重写(以摆脱continue语句),以便从for循环体中创建一个新函数.当你使用更多嵌套的continue语句获得更大的主体时,清理代码需要花费大量的时间. (2认同)

Tom*_*cas 6

道格拉斯·克罗克福德可能会有这种感觉,因为他不相信有条件的任务.事实上,他的程序JSlint甚至没有让你这样做,即使Javascript确实如此.他永远不会写:

例1

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

    doSomething(rec);
}
Run Code Online (Sandbox Code Playgroud)

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

例2

rec = getrec();

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

    rec = getrec();
}
Run Code Online (Sandbox Code Playgroud)

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

例3

rec = getrec();

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

    rec = getrec();
}
Run Code Online (Sandbox Code Playgroud)

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

  • @twiz:我的观点也适用于`for`循环和`do`循环.当然他相信*某种循环! (4认同)