each

each(iterator[, context]) -> Enumerable

The cornerstone of Enumerable. It lets you iterate over all the elements in a generic fashion, then returns the Enumerable, thereby allowing chain-calling.

Iterations based on each are the core of Enumerable. The iterator function you pass will be called with two parameters:

  1. The current element in the iteration.
  2. The numerical index, starting at zero, of the current cycle. This second parameter is unused (and therefore undeclared) most of the time, but can come in handy sometimes.

The optional context parameter is what the iterator function will be bound to. If used, the this keyword inside the iterator will point to the object given by the argument.

$break and $continue

The usage of $continue is deprecated. This feature will not be available in releases after Prototype 1.5 in favor of speed. Instead—since your blocks are in fact functions—simply issue a return statement. This will skip the rest of the block, jumping to the next iteration.

Regular loops can be short-circuited in JavaScript using the break and continue statements. However, when using iterator functions, your code is outside of the loop scope: the looping code happens behind the scene.

In order to provide you with equivalent (albeit less optimal) functionality, Prototype provides two global exception objects, $break and $continue. Throwing these is equivalent to using the corresponding native statement in a vanilla loop. These exceptions are properly caught internally by the each method.

Examples

['one', 'two', 'three'].each(function(s) {
  alert(s);
});

[ 'hello', 'world'].each(function(s, index) {
  alert(index + ': ' + s);
});
// alerts -> '0: hello' then '1: world'

// This could be done better with an accumulator using inject, but humor me
// here...
var result = [];
$R(1,10).each(function(n) {
  if (0 == n % 2)
    throw $continue;
  if (n > 6)
    throw $break;
  result.push(n);
});
// result -> [1, 3, 5]

each vs. _each

If you read the main Enumerable page, you may recall that in order for a class to mix in Enumerable, it has to provide the fundamental looping code appropriate to its internal structure. This basic iteration method must be called _each, and it only receives one argument: the iterator function. You’ll find further details on the main page.

Basically, Enumerable.each wraps the actual looping code provided by _each with:

  1. Support for break/continue, as described above.
  2. Proper maintenance and passing of the value/index arguments.

Optimized version

There is a very common use-case that will probably be better taken care of by a specialized variant: the method-calling scenario.

Say you want to invoke the same method on all elements, possibly with arguments. You may or may not want to use the result values. This can be achieved easily with invoke.

This variant usually performs better than each, since it avoids lexical closure costs. However, it does accumulate the result values in an array, which you might not need. At any rate, you might want to benchmark both options in your specific use case.