In mathematics and computer science, a higher-order function is a function that does at least one of the following:
— takes one or more functions as arguments (i.e. procedural parameters),
— returns a function as its result.
— source
As a JavaScript developer I use the array’s high-order functions all the time, and I always wondered how they are implemented, so this post is just a way to implement them that came across my mind recently, however, take these implementations with a grain of salt.
If you look into the polyfill section in MDN for each function you can get a good idea of how it was implemented, I’ll link to some of them in the end.
My goal is to be able to use them from any array we create, so these functions need to be added into the array’s prototype, & if you ask why in the examples I’m using the ‘function’ keyword not the arrow functions, my answer to that the this
binding won’t happen as we expect.
You might also notice that the high-order functions that I’m creating do not treat the array as mutable objects, they just modify it directly, however, it’s easy to make them return new array you can do this by yourself.
* forEachz *
let’s start with the easiest one: ( I’m using quokka.js for the live evaluation, so you will the result as blue color in the code)
I just defined a function & added it inside the array prototype ( lines 1 — 3 ), and this function(high-order) accepts another function and simply I’ll call it for each element in the array, as simple as that.
Here I’m just concatenating ‘Hi’ with each name from the names array using template literals, and log them to the console.
* mapz *
The function ‘mapz’ calls the function you passed for each element in the array, and the return value of your function will be assigned to the current element, so in the end, we’ll have a mapped array.
In the above example, I multiplied each 1 from the ‘ones’ array with a random number.
Here is another example with an array of objects, I will increase the number of money each human has by multiplying it with 10.
* findz*
Here we don’t need to change the array, just return a new array with the items we found.
For each element in the array, we pass it to the function that was passed, and if that returns true we push it into the result array, then we return it, and here we are finding the human with more than 9000 money.
The original find will only return the first element it found, here we return them all, just return the value when the call-back returns true (if you want this behavior).
* filterz *
This function is the same as our ‘findz’ function.
For each element in the array, we pass it to the call-back function, if that returns true we added to the result array.
Here we are filtering the array for objects that has the name of ‘rowad’.
* reducez *
Probably this one is the hardest one in this list when I try to trace the code.
In the below example I’m grouping by name and aggregating by summing the score an array of objects:
This is a little bit hard to understand especially if you don’t know what reduce actually does, but roughly speaking when you use this function ‘reducez’ on an array you need to pass a default value.
This value will be passed to your call-back with the current element so it’s available for each iteration and the return value from your function will be assigned to it(‘previous’).
That gives you an ability to save a state of the iterations, which is very powerful as you can see in the example above.
Here is an explanation to the code above:
- We have an array of objects, each object contains name & score properties & we need to group by and aggregate the values by name/sum(score).
- I called ‘reducez’ with a call-back and a default value of
{}
. - And for each element, I’ll combine the previous object with a new one, which is shaped like this
name: score
into a single object and return it, so this will become the previous on the next iteration (calling ‘previous’ as ‘accumulator’ is a good idea, which what is in the docs). - If you asked what is
previous.score || 0
this will resolve to zero if the ‘previous’ object does not contain a score, I did this so I won’t get NaN as a result.
Honestly, it took me some time to understand these things and to be able to do the above code without googling just from my understanding, so I hope this was useful to you in any way.
YouTube Videos with the same content:
— .filter
— .map
— .forEach
I’ll leave you with links that contain very informative content.
— reduce
— find
— filter
— map
— forEach
— this