loading...
Cover image for Let's write the most famous JavaScript function together: Array.map

Let's write the most famous JavaScript function together: Array.map

shimphillip profile image Phillip Shim ・3 min read

The map method is one of the most well-known Array methods in JavaScript. It's a handy way of transforming an array without modifying it to fit your needs. Today, Let's dissect the map method and implement it ourselves to understand what happens under the hood 📚.

Array.prototype.map

We should first talk about what it does first. If you already know what it does, feel free to skip to the next section. I will give my best try to explain the concept.

The map method is a higher-order function (A function that takes in a function as arguments or returns a function) that executes a passed in callback function on each of the items in the invoked array. Upon the completion of the iteration, it returns a newly transformed array that contains the results. Here are 2 examples

const numbersArray = [1, 2, 3, 4, 5]

// example 1
const squaredValues = numbersArray.map((number) => {
  return number * number
}) // => [1, 4, 9, 16, 25]

// example 2: conditional mapping
const squaredEvenIndexValues = numbersArray.map((number, index) => {
  if(index % 2 === 0) {
    return number * number
  }

  return number
}) // => [ 1, 2, 9, 4, 25 ]

Strategy

Essentially there are 2 approaches we can take. We could add make it part of the Array prototype. We could get access to the array using this keyword.

Array.prototype.myMap = function(){
  this
}

But this approach is not ideal because it creates unexpected results where an array could be iterated and its properties can spill out unwarranted. ESlint will complain as well.

Array prototype is read-only, properties should not be added. (no-extend-native)

The better approach is simply creating a regular function that takes in an array as an argument☑. Here is how it would be used.

myMap(['hello', 'my', 'name', 'is', 'phillip'], (item) => {
  return item[0].toUpperCase() + item.slice(1)
}) // => [ 'Hello', 'My', 'Name', 'Is', 'Phillip' ]

The above code capitalizes every word inside an array and returns a new array with it. Let's breakdown what's going on with this snippet.

  1. myMap takes an array as the first argument and a callback function as the second argument.
  2. The callback function is supplemented with each item as the first parameter.
  3. Once an operation is done in the function, the value is returned.
  4. The original array is not mutated. A new array is received with new values.

Armed with this knowledge, let's shake and bake.

Implementation

Let's start out with our boilerplate by creating a skeleton code with a basic setup.

const myMap = (array, fn) => {
  const results = []

  return results
}

We could've used callback instead of fn too. We already know we will be returning a new array so this is included ✌. Then we need to invoke the callback function on every iteration.

const myMap = (array, fn) => {
  const results = []

  for(let i=0; i<array.length; i++) {
    fn()
  }

  return results
}

Remember that we are passing each item to the callback function and replace each value with the modifier!

const myMap = (array, fn) => {
  const results = []

  for(let i=0; i<array.length; i++) {
    const item = array[i]
    results.push(fn(item))
  }

  return results
}

There it is, this is the jist of the map method. However, we are not done yet. I haven't disclosed the full details of the map method. In addition to receiving each item inside the callback function, index and the array itself are passed as the rest of the arguments. So the code would like this now.

const myMap = (array, fn) => {
  const results = []

  for(let i=0; i<array.length; i++) {
    const item = array[i]
    results.push(fn(item, i, array))
  }

  return results
}

🌸 Awesome there it is! That wasn't too bad. The hurdles to get through when you are implementing native functionalities are actually trying to read word by word how you are using them in your actual codes and imagine what's going on underground. How about now you try to go and implement the 'filter' or even more difficult 'reduce' methods now? Doing so will give you aha moments that will strengthen ✊ your JavaScript skills.

Thanks for reading! 🙌.

Discussion

pic
Editor guide
 

Love this! Great idea to break down commonly used, built-in functions and be able to recreate them. Maybe I should give one of those a go!

 

Thanks. Definitely, we learn the most when we take action!