Question

I'm new to functional programming, and attempting to glean knowledge by reverse engineering some key Underscore functions. Since _.each is foundational, I though I'd start there. Here's my pared down (for simplicity) version without error checking, context binding, and a bunch of other Underscore awesomeness:

var myEach = function(collection, iterator) {
    if (collection instanceof Array) {
      for (var i = 0; i < collection.length; i++) {
        iterator(collection[i], i, collection);
      }
    } else {
      for (var key in collection) {
        iterator(collection[key], key, collection);
      }
    }
  };

General comments are welcome, but my question specifically revolves around those (collection[i], i, collection) arguments being passed to iterator.

What's going on here? How is it that these arguments become optional during usage?

Pretty sure that it has something to do with the arguments object, but I'd really like to understand what's going on behind the scenes.

Thanks!

Was it helpful?

Solution

In javascript, the caller of a function decides what arguments it is going to pass the function it is calling.

The function being called can then decide which of those arguments it cares to use or not use. So, the iterator callback can be declared however it wants to be. The first argument will the item being iterated, the second will be the index into the collection and the third argument will be the collection itself.

If the callback is declared with only the first argument, then that doesn't really matter. All three arguments are there whether the callback declares them or not, they just can't all be accessed via a named parameter if they aren't declared in the function declaration, but they are all there in the arguments object.


Maybe this gives you some idea:

function callMe(callback) {
    callback(1, 2, 3);
}

callme(function(a) {
    // a === 1
})

callme(function() {
    // all the arguments are still there
    // even though none are declared
    // arguments[0] === 1
    // arguments[1] === 2
    // arguments[2] === 3
});

callme(function(a, b, c) {
    // a === 1
    // b === 2
    // c === 3
})

callme(function(a, b, c, d) {
    // a === 1
    // b === 2
    // c === 3
    // d === undefined
})
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top