63

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?

Community
  • 1
  • 1
twiz
  • 6,335
  • 5
  • 35
  • 67
  • The keyword `continue` is a tool - use it where applicable. SOmetimes it's necessary, most times it isn't. The only time it's bad is when you didn't need to use it but were too lazy or sloppy to do it another way. – slugster Jul 30 '12 at 20:06
  • I had the same feeling and that's why I made my [post](http://stackoverflow.com/questions/30030033/continue-statement-confusion). What helped me is to just think of the word `hop` when using continue statements. I think Mr. Crawford used a poor word of choice here when designing the language :P Especially since hop can apply the logic 'continue' behind it. If you hop over something you're usually continuing as well. Think of marathon track runners as a good analogy. – NiCk Newman May 04 '15 at 12:56
  • 5
    "Mr. Crawford" didn't design the language. – rlemon May 05 '15 at 23:11
  • Someone should write a book called “JavaScript: The Good Parts: The Good Parts”. Frankly, I think a lot of advice in the original should be taken with a grain of NaCl, if not a wole salt mine. – Manngo Mar 29 '18 at 03:58
  • 2
    The more I read about Crockford the less I respect his opinion. He seems to just be a cranky old gatekeeper with entirely irrational preferences of taste which he disguises as experience-honed wisdom. – iono Aug 19 '18 at 03:30
  • @rlemon Neither did Mr. Crockford. – TylerH Sep 03 '19 at 21:09
  • 1
    @TylerH Can we mark Mr. Crockford as "primarily opinion-based"? lol – twiz Sep 07 '19 at 16:32
  • @twiz Absolutely. – TylerH Sep 07 '19 at 18:24

6 Answers6

72

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.

egrunin
  • 23,366
  • 5
  • 44
  • 92
  • I'd also add that readability is subjective and while most people seem to like using continue, others may not. For the same reason, people hate gotos, which are not inherently evil (only abuse of gotos is evil). – Wug Jul 30 '12 at 20:06
  • See my post [here](http://stackoverflow.com/questions/30030033/continue-statement-confusion). I think the word choice is just wrong, I think `hop` should of been a better word used. But it's too late now! – NiCk Newman May 04 '15 at 12:54
  • Using `continue` also allows reading code more in a *functional* style, for example: `for(a in b) { if (condition1) continue; if (condition2) continue; doSomething(); }` is similar to `b.filter(condition1).filter(condition2).forEach(a => ...);` – Stephen Chung Jul 21 '17 at 09:50
8

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.

jJ'
  • 2,890
  • 29
  • 25
  • 5
    I am not sure I know what you mean. Would you mind giving an example of where `continue` will become a "nightmare to refactor"? Also, what do you mean by "extract function"? Is this a design pattern? – twiz Jul 30 '12 at 22:08
  • 2
    "extract function" (also can be googled under "extract method") is a refactoring technique to extract part of body of a function to a new separate function. Even the simple code in another answer here with 2 continue statements would need to be rewritten (to get rid of continue statements) in order to create a new function out of the body of the for loop. When you get bigger bodies with more nested continue statements, it takes a lot of time to clean up your code. – jJ' Jul 31 '12 at 00:31
7

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.

Tom Lucas
  • 116
  • 1
  • 3
  • You may have a point, but I believe he also generally opposes `while` loops in the first place. – twiz Jul 27 '14 at 01:21
  • 4
    @twiz: My point applies to `for` loops and `do` loops as well. Surely he believes in *some* kind of loop! – Tom Lucas Jul 27 '14 at 01:28
  • `rec = getrec();` appears twice, violating Don't Repeat Yourself. – Damian Yerrick Jun 30 '16 at 15:15
  • @twiz as of his latest book, he uses `while (true) { ... }` when he is inclined to use a loop instead of a (preferred) recursive function. – diachedelic Jun 25 '20 at 01:22
  • @diachedelic What is his latest book? Just an updated version? – twiz Jun 25 '20 at 11:29
  • @twiz https://howjavascriptworks.com/ – diachedelic Jun 26 '20 at 00:29
  • @diachedelic Thanks. I might have to give it a read, although I read the sample chapter and the "Heresy" section is probably one of the most arrogant things I have ever read. It's truly astounding. Crockford is obviously a smart guy, but I doubt I could be friends with him. haha – twiz Jun 26 '20 at 15:08
  • @twiz maybe...but everything he says there seems true to me – diachedelic Jun 26 '20 at 22:08
2

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.

Travis J
  • 77,009
  • 39
  • 185
  • 250
2

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.

1

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.

Brock B.
  • 357
  • 1
  • 13
  • So true. To add to your answer, the transpiler internally adds the equivalent of a `continue` statement onto the end of every loop in the generated assembly. So realistically, not only are continue statements not bad, in fact they are actually very good. – Jack Giffin Jul 16 '17 at 21:04