It seems that one of the top complaints about the Array.prototype.forEach() function is the fact that there is no easy way to break out of the loop. If you are one of those people that would like to see an implementation, here you go:


function forEach(arr, fn, thisObj) {
  // Try-catch surrounds the loop to allow throwing the array as an equivalent
  // for breaking out of the loop.
  try {
    for(var i = 0, len = arr.length; i < len; i++) {
      fn.call(thisObj, arr[i], i, arr);
    }
  }
  catch(e) {
    // If the error thrown was not the array, allow the error to continue up the
    // stack.
    if(e !== arr) {
      throw e;
    }
  }
  
  // Return a reference to the array to all for further manipulation.
  return arr;
}

Calling this function would be similar to using Array.prototype.forEach.call() to call the forEach() function introduced in JavaScript 1.6. Here is an example call will break out of the loop as soon a perfect square is found:


var perfectSquare;
forEach([2,3,5,6,7,8,9,10,16], function(num, index, arr) {
  var sqrt = Math.sqrt(num);
  if(sqrt == parseInt(sqrt, 10)) {
    perfectSquare = num;
    throw arr;
  }
});

alert(perfectSquare);  // first perfect square found

For proof that this actually works, you can check out this JSBin page.

As you see in the code, in order to break out of the loop, you will need to throw the array that you are traversing. As you may have guessed, you can also fake the continue action by simply using return.

Categories: BlogJavaScriptJScript

4 Comments

cwest · July 5, 2011 at 3:16 PM

If you would like to use Dean Edward’s suggestion and throw the StopIteration error to break out of the loop without having to catch the error, you can use the following the function:
[code language=javascript]
// Use a closure to prevent the global namespace from be
// polluted.
(function() {
// Define StopIteration as part of the global scope if it
// isn't already defined.
if(typeof StopIteration == "undefined") {
StopIteration = new Error("StopIteration");
}

// The original version of Array.prototype.forEach.
var oldForEach = Array.prototype.forEach;

// If forEach actually exists, define forEach so you can
// break out of it by throwing StopIteration. Allow
// other errors will be thrown as normal.
if(oldForEach) {
Array.prototype.forEach = function() {
try {
oldForEach.apply(this, [].slice.call(arguments, 0));
}
catch(e) {
if(e !== StopIteration) {
throw e;
}
}
};
}
})();
[/code]

The above code will give you the ability to run code such as the following without having to do your own try-catch clauses:
[code language=javascript]
// Show the contents until you get to "2".
[0,1,2,3,4].forEach(function(val) {
if(val == 2)
throw StopIteration;
alert(val);
});
[/code]

K.J. · May 7, 2013 at 9:51 AM

There’s also the some() function on the array prototype in ECMAScript 5.

Chris West's Blog » JavaScript – forEach with Breaking · June 30, 2011 at 6:56 PM

[…] post: Chris West's Blog » JavaScript – forEach w&#1110th Contravention share: Blog this! Bookmark on Delicious Digg this post Recommend on Facebook Buzz it up share via […]

Sublimer ses boucles en javascript | Maxlab Maxlab · May 1, 2014 at 9:05 AM

[…] bidouillant on peut quand même s’en sortir en  levant un erreur mais il y a […]

Leave a Reply to Sublimer ses boucles en javascript | Maxlab Maxlab Cancel reply

Your email address will not be published. Required fields are marked *