5 ms·
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
by brokentone 13y ago
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/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).
- dclowd9901 13y agoI 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.
- cdumler 13y agoThe reason to use it when you have a lot of conditional behavior tied to processing that can stop a process. With traditional code you have really two choices: highly-nested conditionals (or lots of utility subroutines) or using thrown errors for process control (which isn't their purpose). With labels, you're using process control for process control. In my experience, labels generally come into play for data processing, where often the desired behavior is not known until substantial decoding occurs. For made-up instance: var rec = dataStream.next() // Stream sorted by lastName processAtoM: while(rec) { // Stop at N's var lastName = rec.person.lastName.toUpperCase(); if(lastName === 'N') break processingLoop; processRecord: do { // We don't want deleted records. if(rec.deleted === true) break processRecord; // We don't want employee senior management, contractors or founders. var employeeType = Persistence.employeeType.find(rec.company.employeeType); if(['senior management', 'contractor', 'founder'].indexOf(employeeType) !== -1) break processRecord; // Management was never sane about history structures.. FML var history = someWackyDataStructureProcessThatIsPrettyIntensive(rec); // At least I can be functional with this part. var totalPromotions = _.reduce(history, function(total, item) { if(item.promoted || item.lastPromotion !== undefined) { total += 1; } return total; }, 0); // After people with 2 or more promotions if(totalPromotions < 2) break processRecord; // More conditions.. // Finally, this is still an interesting record. var outputRec = someFormattingProcessToOutputFormat(rec); outputStream.write(outputRec); } while (false); rec = dataStream.next(); }