8 ms·
Use labels to break ifs in JavaScript
- oelmekki 13y agoI'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 13y agoThe 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 }
- deleted 13y ago[deleted]
- 0x0 13y agoSeveral languages support labels with "break" and "continue". It's mostly useful to break out several layers at once (nested loops, etc). See for example Java: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html http://docs.oracle.com/javase/tutorial/java/nutsandbolts/bra...
- VMG 13y agoInteresting, 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.
- mradmin 13y agoI 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 13y agoI've been programming in JS since early 2000 and I've only ever used it to break out of nested loops.
- andypants 13y agoThe last two snippets of code are not equivalent. The second if in the second piece of code should be: if (condition && !anotherCondition) {
- rthor 13y agoIt has been updated! Thanks for the heads up!
- brokentone 13y agoI'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/Reference/Statements/label https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... 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 13y agoEDIT: 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.
- rainforest 13y agoOne debatable potential improvement to your alternative could be to use the `do { } while(false)` idiom - that removes the need to preserve the terminating break (and the chance of it being accidentally removed).
- _rs 13y agoI'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 13y agoDijkstra is turning over in his grave.
- dljsjr 13y agoThis 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.
- stephengillie 13y agoThis method of breaking loops from the inside reminds me of the code obfuscation referenced in the HDD Hacking article [1]. Making code hard to read definitely seems like one use of this technique. So I suppose the converse is true -- if you want your code to be easily readable, refactoring is a better way of solving the problem than label-loop-terminating. [1]https://news.ycombinator.com/item?id=6148347 https://news.ycombinator.com/item?id=6148347
- jmilkbal 13y agoTo 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 13y agoI'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.
- madsravn 13y agoI 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.