Using break and continue in each() and forEach()

2020-06-27 02:32发布

I am not sure I understand the value of the functional style looping/mapping if we can't use the break and continue keywords.

I can do this:

collections.users.models.forEach(function(item, index) {
    //can't use break or continue...?
});

or I can do this:

for (var i = 0; i < collections.users.models.length; i++) {
     if (user.username === collections.users.models[i].username) {
         app.currentUser = collections.users.models[i];
         break;
     }
}

what's the advantage of the functional call if I can't use the break or continue keywords?

标签: javascript
5条回答
▲ chillily
2楼-- · 2020-06-27 02:51

You can't natively break from forEach or each callback function. However, there is a technique many people use to break from this with customized exception:

var BreakException = function(){};

try{
    list.forEach(function(el){
        if (meetCriteria(el)){
            throw BreakException; // Break from forEach
        }
    });
}
catch (e){
    // Catch break
    if (e != BreakException) 
        throw e; // If not a break, but other exceptions, raise it
}

// Carry on

Simple approach above is creating a BreakException object and raise it whenever you want to break from the unbreakable loop. Catch that particular BreakException and carry on what your function does.

One thing to remember, always check if the caught exception is BreakException as you defined, since the other possible exceptions (like TypeError, etc) also got trapped by this catch statement. Don't swallow it without checking.

查看更多
三岁会撩人
3楼-- · 2020-06-27 02:56

Using Array.prototype.some and Array.prototype.every to continue/break out of functional for loops is a good thing to do

[1,2,3,null,5].every(function(v){
    if(!v) return false;  // this will break out of the loop
    // do your regular loopage lulz
});
查看更多
Viruses.
4楼-- · 2020-06-27 03:00

each expresses your intent: to iterate and perform a side effect for each item. each abstracts the process of iterating: initializing and incrementing a counter, fetching by array index. That's what the functional combinators do.

Your code snippet is a great example. Let's rewrite that in a functional style:

app.currentUser = collections.users.models.find(function (u) {
  return u.username === user.username;
});

find clearly expresses your intent and abstracts the concept of iterating until you find an item matching your predicate.

查看更多
该账号已被封号
5楼-- · 2020-06-27 03:02

.each() or .forEach() are less flexible than a plain for loop. They just are.

As you have discovered, they offer you less control over the looping. They are a convenience ONLY when you want to iterate the entire set or when it really helps you to automatically have a new function context for your loop iteration code (sometimes useful in async operations) or when you enjoy the more declarative coding in that using the method expresses your coding intent a little more clearly and succinctly than the for loop. .forEach() will also automatically skip sparse elements of an array.

Other than those features, they are just a reduction in typing that sacrifices some looping control. Use them when you like one of the advantages and don't use it when you need more looping control.


FYI, for Javascript arrays, .some() and .every() attempt to get you back some looping control, though they are still not as flexible as a for loop.

If you use .some(), you can return true; to be the equivalent of break; (since that will stop the looping) and you can just return; to be the equivalent of continue; (since that will return from the callback and advance to the next iteration).

查看更多
叼着烟拽天下
6楼-- · 2020-06-27 03:03

To be honest, there is not much of an "advantage" so much as a convenience. You can call return to force yourself out of a single iteration of a forEach loop, but this is not the same as the native for because you are still invoking a function. The convenience comes in the form of not having to define the parameterization of your loop (ie. start point, end point, step size) as well as providing the value of the index and item in the items iterated over.

It is worth mentioning that this convenience comes at the cost of for loop control (ie. start point, end point, step size), backwards iteration, the ability to break the entire loop, a small performance impedance, and yes, even cross browser compliance.

查看更多
登录 后发表回答