Search code examples
javascriptarraystraversal

Eloquent JavaScript. Abstracting Array Traversal. 2nd Ed. pg 83


I can't figure out how this works. Here's the code.

function forEach(array, action) {
  for (var i = 0; i < array.length; i++) 
    action (array[i]);  
}
var numbers = [1, 2, 3, 4, 5], sum = 0;
forEach(numbers, function(number) {
  sum += number;
});
console.log(sum);

I get that sum =+ number; is getting passed to forEach and looping through the array numbers. But I can't make out the details of how that happens. Putting function(number) {sum =+ number} in place of action like so

for (var i = 0; i < [1, 2, 3, 4, 5].length; i++)
  function(number) {
    sum += number;
  } (array[i]);
}

doesn't make sense, nor does it run. What would work is

var numbers = [1, 2, 3, 4, 5], sum = 0;
for (var i = 0; i < numbers.length; i++)
  sum += (numbers[i]);
debug(sum);
console.log(sum);

which is as much as I can compress it and make it work. But how do you get to here? In other words what's really happening?

Thanks for any help. This concept seems basic to Haverbeke's approach, so I think I'd better understand it.


Solution

  • The forEach function is calling action for each element in the array.

    All forEach is doing here is abstracting away a loop like the one you pretty much had:

    for (var i = 0; i < numbers.length; i++){
        sum += numbers[i];
    }
    

    Maybe the action (array[i]) tripped you up. Understand that this is invoking action with the element in the array, so more intuitively it would look like action(array[i]).

    For foreach, this invocation is taken care of inside of the code -- at the action (array[i]). That's why you can just pass a function without calling it yourself.

    In a sentence, forEach works by calling a function your provide on each element in an array you provide.

    If you need another example to clear this up, consider this (Assume that forEach is the one in your question):

    var greetings = ["Hello", "Hi", "How are ya"];
    
    function printGreeting(greeting){
        console.log(greeting, "Greg");
    }
    
    forEach(greetings, printGreeting);
    

    As you can see here, printGreeting is getting called on all of the elements in greetings by being passed each value of greetings[i].

    Anything you would do with a for loop over an array can be done perhaps more easily using the forEach loop.

    For more info, check out the standard Array.prototype.forEach() here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach