# JS Rewrited #01 - Array.map()

## Summary

In this article, we will discuss what the *Array.map* function is, its usage, and recreate its behavior by creating a brand new custom function to get a deeper understanding of how it works in detail.


1. The *map* function
2. Usage
3. Function rewriting
4. Resources
5. Conclusion

## 1. The *map* function

Array's map function is nothing more than a functional way to transform each one of the elements of an array into something else.

Basically, this function takes as input a *callback* function provided by the developer and an optional *thisArg* (value to be used as *this* by the callback). It has the following signature:

```
Array.map(callbackFn(currentElement, currentIndex, currentArray), thisArg)
``` 

It accepts two inputs:
- *callbackFn*: a function provided by the developer to perform any operation in the element of the array. It **must return ** the new intended value which the element is being mapped into. 
This function can receive three arguments:
    - *currentElement* : the current element being iterated.
    - *currentIndex* : the current index of the element being iterated.
    - *currentArray* : the current array object.

- *thisArg* : the value used as *this* by the provided *callbackFn*. This is an optional argument.

The returned value of this function is a brand new array containing all the mapped elements.



## 2. Usage

In this simple example, a function to square a number was defined to be used as the *map's* callback. Given an array of numbers, each one of the elements will be mapped to its squared value in a brand new array as the result of the map operation.

For the sake of simplicity, the *thisArg* was omitted.

```
/* Defines a squaring function to be used as a callback argument */
function squareFn(currentElement, index, currentArray){
   return currentElement**2;
}

const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(squareFn);
/* Prints the brand new generated list */
console.log(squaredNumbers);
/* output: [1, 4, 9, 16, 25] */
``` 

Interesting gotcha:

- If you wish to use the optional parameter *thisArg*, be sure your callback function definition is done in the standard way (`function myFunc(){}`), not with an arrow function  expression (`const myFunc = () => {}`). This is required for the binding of the custom *this* value to work properly inside the provided callback since the arrow function binds its context to its lexical scope.

## 3. Function rewriting

Have you ever wondered what kind of magic provides the argument's values to the callback function?

Knowing what the map function does, it is possible to recreate it with a new function that replicates its behavior to get a better understanding of how it works under the hood. This can be done by adding a new custom function to the javascript *Array* object with the following implementation:

```
Array.prototype.customMap = function(callback, thisArg) {
    /* Sets the "this" context to be used within the callback function, defaults to the array which this function was called. */
    const _this = thisArg || this;
    const mappedArr = [];
    /* For each element, the callback function is called passing the provided context for "this" keyword */
    for(let i = 0; i < this.length; i++) {
        mappedArr.push(callback.call(_this, this[i], i, this));
    }
    return mappedArr;
};
```

You can test the new *customMap* function by replacing the *map* call that was done previously. The same output should be displayed. 

```
const squaredNumbers = numbers.customMap(squareFn);
```


PS.: This implementation might differ from the native one implemented by browsers.

## 4. Resources 

For further reference: 

-  [MDN - Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) 
-  [MDN - Callback function](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function) 


## 5. Conclusion

This article aimed to give a deeper understanding of how the array's *map* function works under the hood. The "magic" under the map function was demystified by recreating its implementation according to the function's original behavior.

<hr>

