

Use labels to break ifs in JavaScript  - rthor
http://rthor.is/javascript/quick-tip-labeled-ifs/

======
dljsjr
This is not unique to JavaScript. You can do this in many languages, including
Java. In fact, the JDK source is littered with usages of this "pattern", but
with loops instead of if statements. It is frequently used as a technique to
capture a terminal event in an inner loop that requires termination of the
entire nested looping construct; in other words, the label is applied to the
outer loop but the break statement occurs somewhere in an inner loop.

99.9% of the time, when I'm writing nested loops and I find myself needing the
ability to kill the outer loop from within the inner loop, this is a flag that
I need to refactor or re-evaluate my design, not start using labels and
breaks.

~~~
jmilkbal
To the contrary, labels and breaks are the better design because they are far
clearer than testing for termination in each outer loop. Get more than two
loops deep and your problem suddenly becomes unmanageable without labels and
breaks.

However, if there are other actions like logging or reporting that are
occurring it may be better to not use them. Here's some Ada:

    
    
      Outer: loop
        Inner: loop
          Handle_Head: declare
            Head : Human_Head;
          begin
            Acquire_Head (Head); -- Entry will block until head is acquired.
            exit Inner when Head = No_Head;
            exit Outer when Head.Exploded;
            Log ("Head unexploded.");
          exception
            when Brain_Error =>
              Log ("Brain deficiency detected.");
          end Handle_Head;
        end loop Inner;
        Log ("Head exploded.");
      end loop Outer;

~~~
dljsjr
I'd argue that if you're more than 2 loops deep then you should, as I stated
before, seriously evaluate your design decisions.

And, should you do so and end up in the same place, you may have stumbled upon
that 0.1% of the time that I left wiggle room for in my first claim.

------
brokentone
I'm having a hard time finding a reason to use this, I've always understood
named breaks and named gotos as antipatterns, and MDN recommends you not use
them as much as possible (if nothing else because they're uncommon).
[https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Statements/label)

The irregularity of these functions are not lost on the author, who improperly
claims the following code is equivalent:

myTest: if ( condition ) {

    
    
        // some code...
    
        if ( anotherCondition ) break myTest;
    
        // more code if anotherCondition is falsy...
    

}

if ( condition ) {

    
    
        // some code...
    

}

if ( !anotherCondition ) {

    
    
        // more code if anotherCondition is falsy...
    

}

While the second comment will run for the same value of "anotherCondition," in
the first, "condition" also must be true, and the second does not evaluate
"condition" to run the comment.

~~~
delinka
EDIT: That this JS feature lets the developer break an outer scope from an
inner scope is pretty awesome. I should ponder whether I can conjure this in
C...

====

I'm with you. Now, take the case of a function that can return "early" \-
because it hit a condition that prevented it doing its job, or because it
finished early on in its code. I've recently been requiring such functionality
in places that have accumulated resources which should be released or
otherwise tidied before returning. My fellow co-workers have been using goto,
and at the label freeing the resources. My solution is to use 'while' and
break (you could certainly use 'for' instead):

    
    
      struct some_object *o = some_object_create(); // maybe you alloc here, and set properties
      OtherType *result = NULL;
      
      while(true) {
        if (cond_based_on_args) {
          result = OtherTypeCreate(...);
        }
        if (!result) break;
        if (OtherTypeGetValue(result) != kCorrectValue) {
            OtherTypeFree(result);
            result = NULL;
            break;
        }
        
        /* Other work to do with 'result' */
        
        break; // never let it run again
      }
    
      some_object_free(o);
      
      return r;
    

This code is a bit contrived, but I think it illustrates the idea.

~~~
dclowd9901
I would use Promises to handle the situation of "returning early."
Essentially, you create recursive function, and execute it in a setInterval
(don't forget to bind the scope if you're doing class references!). Manage
state outside the scope of the function and create a deferred object outside
the scope as well. When it's done, resolve the promise and kill the .

Elsewhere, use the resident "when" function to capture the resolved state.
This helps create a very secular structure of code where each method is
purposeful.

------
mradmin
I would probably only use labels for breaking out of nested loops, for
example:
[https://gist.github.com/badsyntax/5317545](https://gist.github.com/badsyntax/5317545)

~~~
xutopia
I've been programming in JS since early 2000 and I've only ever used it to
break out of nested loops.

------
_rs
I've had the experience of using labels exactly 1 time so far, in this code:
[https://gist.github.com/RSully/5262735](https://gist.github.com/RSully/5262735)

------
dccoolgai
Dijkstra is turning over in his grave.

------
oelmekki
I'm surprised. I've always thought of labels as something to be used with
goto. What is the purpose of labels in javascript, since it does not implement
goto ?

Do you have any idea if it was intended to be used as you describe ?

~~~
VMG
The best I can come up with is this:

    
    
        ANIMAL: if (isAnimal) {
            DOG: if (isDog) {
                POODLE: if (isPoodle) {
                    if (color == green) {
                        break POODLE; // we don't want green poodles
                    }
    
                    if (age > 10) {
                        break DOG; // we don't want old dogs
                    }
    
                    if (weight > 20) {
                        break ANIMAL; // we don't want heavy animals
                    }
    
                    // more poodle conditions
                }
    
                // more dog conditions
            }
    
            // more animal conditions
        }

------
andypants
The last two snippets of code are not equivalent.

The second if in the second piece of code should be:

    
    
        if (condition && !anotherCondition) {

~~~
rthor
It has been updated! Thanks for the heads up!

------
VMG
Interesting, but I'd probably need 10 seconds more to understand code that
uses this than code that doesn't use it. I'm wondering if there is a real
benefit to this.

------
madsravn
I knew this trick from C++. And while it's a fun example, I believe it ruins
the natural flow of your code. So please don't.

