Why are “continue” statements bad in JavaScript? [closed]

In the book Javascript: The Good Parts by Douglas Crockford, this is all the author has to say about the continue Statement:

The continue statement jumps to the top of the loop. I have never seen a piece of code that was not improved by refactoring it to remove the continue statement.

This really confuses me. I know Crockford has some very opinionated views on JavaScript, but this just sounds entirely wrong to me.

First of all, continue does more than just jump to the top of a loop. By default, it also progresses to the next iteration. So isn't Crockford's statement just completely false information?

More importantly, I do not entirely understand why continue would even be considered to be bad. This post provides what seems to be the general assumption: Why is continue inside a loop a bad idea?

Although I understand how continue may make code difficult to read in certain instances, I think it is just as likely that it can make code more readable. For instance:

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

This could be refactored into:

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 isn't particularly beneficial in this specific example, but it does demonstrate the fact that it reduces the nesting depth. In more complex code, this could potentially increase readability.

Crockford provides no explanation as to why continue should not be used, so is there some deeper significance behind this opinion that I am missing?

Answers:

Answer

The statement is ridiculous. continue can be abused, but it often helps readability.

Typical use:

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

    some_provisional_work_that_is_almost_always_needed();

    if (!further_tests()) continue;

    do_expensive_operation();
}

The goal is to avoid 'lasagna' code, where you have deeply nested conditionals.

Edited to add:

Yes, this is ultimately subjective. Here's my metric for deciding.

Edited one last time:

This example is too simple, of course, and you can always replace nested conditionals with function calls. But then you may have to pass data into the nested functions by reference, which can create refactoring problems at least as bad as the ones you're trying to avoid.

Answer

I am personally on the other side than the majority here. The problem is usually not with the shown continue patterns, but with more deeply nested ones, where possible code paths may become hard to see.

But even your example with one continue does not show improvement in my opinion that is justifiable. From my experience a few continue statements are a nightmare to refactor later (even for static languages better suited for automated refactoring like Java, especially when someone later puts there break too).

Thus, I would add a comment to the quote you gave:

Refactoring to remove continue statement inreases your further ability to refactor.

And inner loops are really good candidated for e.g. extract function. Such refactoring is done when the inner loop becomes complex and then continue may make it painful.

These are my honest opinions after working professionally on JavaScript projects in a team, there rules that Douglas Crockford talks about really show their merits.

Answer

Douglas Crockford may feel this way because he doesn't believe in assignment within a conditional. In fact, his program JSlint doesn't even let you do it, even though Javascript does. He would never write:

Example 1

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

    doSomething(rec);
}

but, I'm guessing he would write something like:

Example 2

rec = getrec();

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

    rec = getrec();
}

Both of these work, but if you accidentally mix these styles you get an infinite loop:

Example 3

rec = getrec();

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

    rec = getrec();
}

This could be part of why he doesn't like continues.

Answer

Continue is an extremely useful tool for saving computation cycles in algorithms. Sure, it can be improperly used but so can every other keyword or approach. When striving for performance, it can be useful to take an inverse approach to path divergence with a conditional statement. A continue can facilitate the inverse by allowing less efficient paths to be skipped when possible.

Answer

Actually, from all the analysis it seems:

  1. If you have shallow loops - feel free to use continue iff it improves readability (also, there may be some performance gains?).
  2. If you have deep nested loops (which means you already have a hairball to untangle when you re-factor) avoiding continue may prove to be beneficial from a code reliability standpoint.

In defense of Douglas Crokford, I feel that his recommendations tend to lean towards defensive programming, which, in all honesty seems like a good approach for 'idiot-proofing' the code in the enterprise.

Answer

Personally, I have never heard anything bad about using the continue statement. It is true that it could (most of the time) be easily avoided, but there is no reason to not use it. I find that loops can be a lot cleaner looking and more readable with continue statements in place.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.