Joss Classey
Joss Classey

Reputation: 1062

How do higher-order functions like `map()` and `reduce()` receive their data?

I'm trying to write my own higher order function right now and I want to know how functions like map() and reduce() access the array they are being applied to. And not just for arrays either, but with any higher order function like toString() or toLowerCase().

array.map()
^^^ // How do I get this data when I am writing my own higher order function?

array.myOwnFunction(/* data??? */)

I hope this makes sense. I'm sure the answer is out there already, but I'm struggling to know what to search for to find the information.

Upvotes: 6

Views: 129

Answers (4)

Travis J
Travis J

Reputation: 82297

The way this works is related to the prototype and to the "thisBinding".

When a function is instantiated using new, the properties of the prototype are attached to the new Function object. As well, an "execution context" is created to maintain the environment. The properties of the prototype are then accessible in the environment through the current instance's this binding using this.

So if you have a function you want to use the data from in an instance, you can use a prototype as well. For many reasons (memory use, readability, reusability, inheritance, polymorphism, etc.) this is the best way to go about doing it. Modifying standard implementations such as Array, Math, Date, etc. are generally discouraged (although there will always be exceptions).

function LineItem(description,price,quantity){
 this.description = description;
 this.price = price;
 this.quantity = quantity;
}
LineItem.prototype.Total = function(){
 return this.price * this.quantity;
};

var avocados = new LineItem("avocado",2.99,3);
console.log(avocados.Total());

The main thing to take away here is that the thisBinding allows access to the current instance's object through this. That is where the data access comes from. For example, in an array instance, this references the current array; in a date instance, this references the current date; in the above LineItem example, this references the current LineItem.

Upvotes: 1

Joss Classey
Joss Classey

Reputation: 1062

Thanks to the responses to this question I was able to write a higher order component that accepts a callback function as an argument. Here is the code as an example:

Array.prototype.myFunction = function (callback) {
  const items = this
  const newArray = []
  for (let item of items) {
    item = callback(item)
    newArray.push(item)
  }
  return newArray
}

const array = [1, 2, 3, 4]

const result = array.myFunction((item => {
  return item + 1
}))

console.log(result)

Upvotes: 0

Taki
Taki

Reputation: 17654

You can add it to the Array prototype like :

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

  return this;
};

const array = [1, 2, 3];

const result = array.myOwnFunction();

console.log(result);

Upvotes: 5

silentw
silentw

Reputation: 4885

Check the polyfill for Array.prototype.map(), this line in particular:

//  1. Let O be the result of calling ToObject passing the |this| 
//    value as the argument.
var O = Object(this);

Simplifying, this is where the values are received.

Upvotes: 4

Related Questions