Implement map on a Prototype // Don't understand Solution

I am not understanding the use of the this keyword and how I use the callback function in forEach.


// the global Array
var s = [23, 65, 98, 5];

Array.prototype.myMap = function(callback){
  var newArray = [];
  // Add your code below this line
  this.forEach(item => { 
    newArray.push(callback(item))
  })
  // Add your code above this line
  return newArray;

};

var new_s = s.myMap(function(item){
  return item * 2;
});

Your browser information:

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype

The this keyword refers to the object itself(here which is the array) and in JS arrays can be considered as objects you can write solution without using forEach loop check mine without forEach https://github.com/Cirediallo/FreeCodeCamp/blob/master/ImplementMapOnPrototype.js
Coming back to your question know that your function take a parameter callback which is function itself remember a function can be passed as a parameter to other functions and you can use a callback function in forEach check the docs

The way to understand the callback thing is to dive into parameterization:

Imagine you have these repeated patterns across your codebase:

for currentItem in list
  newItem = currentItem + ' has changed'
  push newItem to newList

for currentNumber in numberList
  squaredNumber= currentNumber * currentNumber
  push squaredNumber to listOfSquares

for personObject in personList
  currentFirstName = personObject.firstName
  push currentFirstName to onlyNamesList

As you can see, the code is reapeted a lot so you can make your own function that “transforms” each element in a list and gives you a new list with the transformed elements.

The question to ask is: What is the thing that is NOT COMMON and the thing(s) that ARE COMMON in the operation?

  • Common: Looping over the list -> Transforming each element -> Sending the result to a new list -> Return new list upon completion
  • Not common: The transformation itself since it varies from use case to use case.

Then, what’s the solution? Parameterizing the actual transformation step that isn’t common between all cases. The things that are common go inside the function “map” and you pass an “action/transformer/mapper” (depends on your favourite terminology) to said function along with the list you want to transform.

JavaScript allows you to store functions inside variables, pass them as arguments to functions, return them from functions and treat them as values (this concept is called "functions as first-class objects). The concept of a higher order function is a function that takes function(s) as parameters, and map happens to be one of those.

Now we can refactor our codebase as follows:

function square (x) = x * x
function changeText (str) = str + ' has changed'
function extractFirstName (person) = person.firstName

function map (transformation, list)
  transformedList = []

  for currentElement in list
    transformedElement = transformation(currentElement)
    
    push transformedElement to transformedList

  return transformedList

map(square, [1 2 3]) # [1 4 9]
map(extractFirstName, [
  { firstName: 'Diego', lastName: 'Rivera' },
  { firstName: 'Lou', lastName: 'Vega' }
]) # ['Diego', 'Lou']
map(addSomeText, ['the world', 'my soul'])
# ['the world has changed', 'my soul has changed']

As you can see, the core concept is that you execute the function that you pass to map inside of it and send the returning value to a new list consisting of transformed elements. It’s like if you had an assembly line and you could replace the people working on it with different people that do what you want to your items at any given time according to your needs.

The difference between map and forEach is that forEach does not return a new list, it only does “something” with every item, and filter instead of accepting a transformation, it accepts what we programmers call a predicate which is just a function that returns a boolean.

Higher order functions for the 4 most used array methods:

1- Reduce: Takes a reducer function that ‘folds’ a list into an accumulated result, this method is very powerful and the other 3 can be declared in terms of this one: (accumulator, item) returns <Accumulated Value>.
2- Filter/Reject: Takes a predicate which evaluates every item and returns either true/false to decide if it stays or goes: (item) returns Boolean.
3- ForEach: Takes an action and this one doesn’t return anything, it just performs a side-effect with each item: (item) returns Void.
4- Map: Already explained what a mapper is lol: (item) returns <Transformed Item>.
5- Find: Takes a predicate (or ‘search condition’) as well, but instead of returning a new list, it returns the first item that makes the predicate return true otherwise it returns undefined (I think).

1 Like