为什么“;继续”;JavaScript中的语句不正确

Why are "continue" statements bad in JavaScript?

本文关键字:语句 不正确 继续 为什么 JavaScript      更新时间:2024-06-13

在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,那么我所缺少的这个观点背后是否有更深层次的意义?

这句话太荒谬了。continue可能被滥用,但它通常有助于的可读性。

典型用途:

for (somecondition)
{
    if (!firsttest) continue;
    
    some_provisional_work_that_is_almost_always_needed();
    if (!further_tests()) continue;
    do_expensive_operation();
}

目标是避免"千层面"代码,在那里你有深度嵌套的条件语句。

编辑后添加:

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

最后一次编辑:

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

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

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

我个人站在这里大多数人的另一边。问题通常不在于所示的continue模式,而在于嵌套更深的模式,在这些模式中,可能的代码路径可能变得很难看到。

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

因此,我想在你的报价中添加一条评论:

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

内环确实是很好的候选者,例如提取函数。这样的重构是在内部循环变得复杂时进行的,然后continue可能会让它变得痛苦。

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

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

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

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

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

就我个人而言,我从未听说过使用continue语句有什么不好的地方。的确,它(在大多数情况下)可以很容易地避免,但没有理由不使用它。我发现,如果有continue语句,循环可以看起来更干净,可读性更强。