Ruby’s “each” for JavaScript

posted in: javascript, ruby, tutorial | 0

Wow! 30 new subscribers due to my last blog posting about JavaScript inheritance: Welcome dear new readers 🙂 Due to this fact I’ve decided to try out something new. No fancy new technologies for showing-off but a tutorial-like introduction to some neat and often unknown JavaScript functions that can make your life easier.

Sine I really love Ruby, I thought: Why not take a use-case from the oh-so-beautiful Ruby world and transfer it to JavaScript. Well, here it is. Nothing new but still pretty cool: Ruby’s “each” for JavaScript.

So, this is an experiment I’ll really appreciate your feedback – is it too trivial or do you like it? Anyway, let’s just start …

In Ruby an array comes with the “each”-method for iterations:

[1, 2, 3].each { |element| puts "#{element}" }

This prints out the numbers 1, 2, 3, i.e. the contents of the array. To perform the same task in JavaScript you do something like this:

var a = [1, 2, 3];
for (var i=0; i<a.length; ++i) {
  var element = a[i];
  alert(i + ": " + element);
}

A for-loop – easy going 😉 And the element assignment inside the loop is kind of redundant in this example but often you perform multiple tasks with the element inside the loop, i.e. most of the time you need this assignment.

Note that you will have to use an additional named variable, e.g. i, for each and every loop – compared to Ruby that feels kind of old-school.

Most JavaScript libraries come with something similar to Ruby’s each method. E.g. Prototype extends JavaScript’s Array.prototype for that and jQuery comes with $.each. You should use these functions if your are working with one of these libraries. I will simply show you, how those functions are implemented.

What we basically want is a function which allows us to do the following:

each([1, 2, 3], function(index) {
  alert(index + ": " + this);
});

Kind of handy, right? You pass in an array plus a function and each array element will be passed via this into the function. Additionally you can access the index parameter and use it inside your loop. No more implicit element assignment and no more visible named variable for counting the index.

And here’s how this each-function is implemented:

function each(array, func) {
  for (var i=0; i<array.length; ++i) {
    func.call(array[i], i);
  }
}

Looks almost like the previous for-loop except that it calls the function provided by func during the iterations.

Tutorial: Every JavaScript function is an object itself and comes with some neat helper methods. One of these methods is function.call. With this method it is possible to call a function in a different context/scope than its original one. The first parameter is this context and it will be accessible via this inside the method’s body. We are supplying array[i] here and hence this inside the method’s body will point to the current array element. The successive arguments will be used as arguments for the method’s call. We are passing in i here which will in turn becomes the first parameter for the method call.

Using our each-method we are pretty close to Ruby – and we can get even closer! JavaScript allows you to extend the prototypes of existing classes – and most of the time this also works with the standard classes of JavaScript, e.g. Array itself.

So let’s try to add our each-method to the prototype of Array:

Array.prototype.each = function(func) { each(this, func); };

The context of this function is per default the array instance. Hence this points to the array itself.

Now we can call each directly on an array instance:

[4, 5, 6].each(function(index) { alert(index + ": " + this); })

… which works and which almost looks like “real” Ruby code 😉