JavaScript Under the Hood – Building Our Own forEach and Map Functions

Iterating over arrays in JavaScript – so useful, so seemingly simple, and so easy to misunderstand. What’s actually going on in forEach? How does Map work? What do Reduce and Filter do?

Every array comes with the forEach, Map, Reduce, Filter, etc. methods built on the prototype. It’s easy to take these functions for granted, but it’s not some JavaScript magic at work – we can build these functions out ourselves. Making these functions from scratch helped to solidify my understanding of the methods and use them more accurately in the future.

forEach

Array.prototype.forEach()

From the Mozilla documentation:

The forEach() method executes a provided function once per array element.

forEach takes two arguments: the array over which you want to iterate and a callback function, which does the actual manipulation of the elements.

The callback function takes three arguments:

  1. currentValue – the current value being processed in the array (in Ruby, this is the variable between the brackets)
  2. index
  3. the array itself

Here is a festive example of forEach:

forEach method JavaScript

As you can see, we’re looping through our holidayJoy array and printing out each element along with its index (+1, since the index starts at 0) in a neatly numbered list. Now pretend that we don’t have forEach in our lives. How would we execute the same operation?

We’ll name our function forEach and it will take in two arguments: the array and a callback (like the built-in forEach). Then we’ll loop through the array with a for loop because that’s what iteration is, right? A bunch of loops?

foreach_from_scratch

In our for loop, i is the index. We are setting it to zero initially, having the loop go through the function as many times as the array length (hitting all the elements), and incrementing the index by 1 each time.

Again, callback takes three arguments: the current value, the index, and the array. Since this confused me at first, let’s look at how the callback is working:

Look at array[i] as array[0] the first time through. That’s how we access the first item in an array, right? Then as the loop repeats, the index of the array increments to array[1], array[2], etc. so that we are accessing each element and performing the callback on said element.

Note that forEach doesn’t return anything. It simply performs the callback function on each element of the array but doesn’t do anything with the results. forEach is good in situations where you don’t need to return a new, modified array – that’s where map comes in!

Map

Array.prototype.map()

Now let’s write Map from scratch. From the Mozilla docs:

The map() method creates a new array with the results of calling a provided function on every element in this array.

That can sound confusing so let’s review what map does step-by-step:

  1. Takes in an array and a callback function
  2. Applies the function to each element in the array
  3. Keeps track of the results of each loop through the array
  4. Returns a new array with those results

Note that map does not modify the original array but returns a new array with the results of the callback function.

Here is the map function built from scratch:

mapfromscratch

Let’s unpack what’s going on here:

We have a function myMap that takes in two arguments – an array and a callback. We set a variable returnValue to an empty array because we will have to return a new array with the results of our callback later.

We have a for loop that works similarly as mentioned above in forEach, except that in each loop, we are setting the result of the callback to a variable called newElements.

Lastly, we are pushing newElements one by one into the returnValue array, then returning that array at the end of our function.

And boom, that’s map in JavaScript.

Resources

Here is a great comprehensive article breaking down map in easy-to-understand terms: https://www.discovermeteor.com/blog/understanding-javascript-map/

facebooktwittergoogle_plusmail

Leave a Reply

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