Implement map on a Prototype - so confused

Since you haven’t marked this question as solved, I’m going to throw in my 2 cents and see if it helps.

Disclaimer:

The following will not always be technically accurate. This is intentional. I’m only trying to give you a mental model to work with. And for that, technical accuracy isn’t always required.


As always, it’s best to clear up some terms. So I’ll briefly go over prototypes just in case you don’t understand them already. Instances, constructors, etc are not necessary to understand prototypes as a mental model.

Prototypes:

In javascript everything except primitives is an object, even arrays.

And you can think of objects in javascript of being just like object literals.

This means you can create an object literal with functions, which we call methods, if you desired.

const obj = {
  sayHi() {
    console.log('Hi!')
  }
}

obj.sayHi() // Hi!

That also means that you can think of the array object as looking like this:

const Array = {
  map() {},
  reduce(){},
  '0': 'index 0 value',
  '1': 'index 1 value'
  length: 2
}

Every time you create an array with [], Array.from(), etc, that array has all those properties attached to it.

If you only had a few array objects this would be fine. But if you plan on creating many then it would needlessly take up memory.

So it’s best that we create a new Array object, but only keep the properties that belong to that specific array.

And those are it’s values. To do that, we place all the shared properties on the prototype.

const Array.prototype = {
  map() {},
  reduce(){},
}

// then

const myArrayOne= [ 0, 1 ]
// same as
const myArrayOne = {
  '0': 0,
  '1': 1,
  length: 2
}

const myArrayTwo = [ 0, 1, 2 ]
// same as
const myArrayTwo = {
  '0': 0,
  '1': 1,
  '2': 2,
  length: 3
}

myArrayOne and myArrayTwo now have all their items, their length prop, as well as the shared prototype methods

myArrayOne.map()
myArrayTwo.map()

myArrayOne[0] // 0
myArrayOne[2] // undefined

myArrayOne.length // 2
myArrayTwo.length // 3

Javascript will first look for the map property in the current object. If it doesn’t find it, it will go up each prototype and check there.

But how do you know which array is the one calling the map method?

This brings us to this

this

this is a complicated term, so the following is a very simple explanation of it.

  • this refers to the object that “owns” the current function scope.

Using that as our definition, if we wanted to add a myMap to the Array protoype

So as you see, your initial instinct was right. You have access to the array and it’s properties inside the function as the keyword this

But right now, this function does not return anything. All you are doing is looping over this

Array.prototype.myMap = function(){
  for(var i = 0; i < this.length; i++){
    this[i]= this[i];
  }
}

So how do we return a value to the caller of the function? We return a callback

Callback

You can think of a callback as just that – calling back to the caller of the function.

With a callback, not only can we return a value, but we let the caller decide what to do with what we send them.

For instance… (make sure to scroll the repl to see all the code)

Now that we know that callback is the function passed in, and the function expects an argument of item, how do we forward that?

We just call the function with it’s expected arguments.

Array.prototype.myMap = function(callback){
  //...

  /* whatever you want to pass back */
 callback(item)
}

And if you want the caller to have access to the index of the current value?

Array.prototype.myMap = function(callback){
  //...

  /* you control what the caller has access to */
 callback(item, index)
}


//...
s.myMap(function(item, index){
  return item * 2;
})

In essence

  • you are calling the function passed in for the caller
  • so you decide what arguments they can use
  • but the caller decides what it returns.

Now to answer your question:

  • You need to call the callback with the arguments the callback expects.

Try saying that 5 times fast. lol

I know this was lengthy, but hopefully I cleared up some of this. If I haven’t or I’ve made it even more confusing, let me know and we’ll get hacking at it.

20 Likes