1

If you have:

var some = [0,1,2,3];
_.forEach(some, function (val) {
    if(val === 1) {
        // this return does nothing
        return;
    }
});

Looking at the underscore source you can break out of forEach using

var breaker = {};

However breaker is not released to public scope and appears to be an internal variable.

  • There is no reason for that to work. To break out of the loop `if (iterator.call(context, obj[key], key, obj) === breaker) return;` –  Jun 11 '13 at 20:35
  • Underscore will use native `forEach` when possible and you can't break out unless you throw exception (ugly!), use `some`, check related http://stackoverflow.com/questions/2641347/how-to-short-circuit-array-foreach-like-calling-break – elclanrs Jun 11 '13 at 20:35

1 Answers1

4

you can use some instead of forEach, which will stop it the first time you return something non-falsy. The opposite is every(), where it stops when you return something falsy.

You still have to pass the data using closure, since .some() will return true or false.

var some = [0,1,2,3];
_.some(some, function (val, index) {
    if(val === 1) {
        // this return does nothing
         alert("exiting at step "+index+" from finding "+val);
        return true;
    }

    alert("continuing at step "+index+" found "+val);
});
dandavis
  • 16,370
  • 5
  • 40
  • 36
  • ok, i added another tattletale so you can see it in action... – dandavis Jun 11 '13 at 20:38
  • @pure_code.mom `some` can break because undescore's `breaker` object is available in `some`'s lexical scope, whereas `breaker` is *not* in-scope for any function your code defines (outside the underscore library). – apsillers Jun 11 '13 at 20:38
  • This will work. `some` lets you exit the function as soon as you return truthy while `forEach` doesn't. – elclanrs Jun 11 '13 at 20:38
  • you don't need breaker at all technically...it simply checks the return value. I'm not sure why it returns the breaker or what good that is to you from the application code. –  Jun 11 '13 at 20:39
  • `if (result || (result = iterator.call(context, value, index, list))) return breaker;` –  Jun 11 '13 at 20:39
  • @pure_code.mom `each` will only break if the iterator function returns `breaker`. `some` can delegate its work to `each` because `some` has the ability to return `breaker`, which can cause a break in `each`. Ordinary functions (defined outside of the underscore library) cannot cause a break in `each` because they don't have scope access to `breaker`. – apsillers Jun 11 '13 at 20:42
  • yikes at all that complication, this is why i just use the native [].some(); faster and simpler... – dandavis Jun 11 '13 at 20:44
  • ...the iterator function does not have access to the breaker so I have no idea what you are talking about...iterator is a user defined function that is supplied to `forEach`. `breaker` is defined inside the underscore library –  Jun 11 '13 at 20:47