This post is NOT a post to show you how to use , , and , is it a post showing the benefits of higher order functions. There are plenty of that. forEach map filter reduce NOR other articles that do When I want to understand a basic concept, I like to try to , even if it is a very basic version. People learn in different ways, this works for me. So let me take you on this journey as I try to create my own , , and functions in . implement it myself forEach map reduce filter JavaScript myForEach In order to disambiguate from the built-in , let’s call my new function . forEach myForEach First thing to do is to look at the call signature. So, the forEach function you know does something like this: let arr = [ 1, 2, 3, 4 ] // log each item of the arrayarr.forEach(console.log) // double each item of the array and log it to the consolearr.forEach((val) => console.log(val * 2)) We’re sort of looking for a function that takes two parameters, an array and callback function. The callback function could be a function definition or an anonymous function. And what we want this to do is to iterate over each item in the array and call the callback on that item. So let’s give it a shot. function myForEach(arr, callback) {for (let i = 0; i < arr.length; i++) {callback(arr[i])}} let arr = [ 1, 2, 3, 4 ] // log each item of the arraymyForEach(arr, console.log) // double each item of the array and log it to the consolemyForEach(arr, val => console.log(val * 2)) Seems simple enough and it works. But … but … it’s not exactly the same. If you try , you get . That is because we declared myForEach as a global function. And really, it should be part of the prototype of the Array object. Note the purpose of this article is not to explain how prototypical inheritance works. In order to achieve what we want, we need to do this as follows. arr.myForEach(console.log) TypeError: arr.myForEach is not a function Array.prototype.myForEach = (callback) => {for (let i = 0; i < this.length; i++) {callback(arr[i])}} // log each item of the arrayarr.myForEach(console.log) When I tried running the code above, nothing happened. What is wrong? Trying to get to fancy with arrow functions. Arrow functions don’t have their own or binding. So when I call inside the function definition, it does not refer to the Array object itself, as I naively expected. Here is the correct way to do it. This has the explanation. this arguments this StackOverflow post Array.prototype.myForEach = function (callback) {for (let i = 0; i < arr.length; i++) {callback(arr[i])}} // log each item of the arrayarr.myForEach(console.log) Beautiful. Now that we have the mechanics down, we can move on to the other higher order functions. myMap The signature is as follows. Imagine we have an array of numbers, and want to get an array of the squares of these numbers. let arr = [ 1, 2, 3, 4 ] let arrNew = arr.map(val => val * val) // orconst squareNumber = n => n * nlet arrNew2 = arr.map(squareNumber) console.log(arrNew)// outputs [ 1, 4, 9, 16 ] So we we apply to an array: a function that takes a callback, and returns a new array. The callback is a function that takes an input value and usually transforms that input value into something else. Array.prototype.myMap = function(callback) {let ret = []for (var i = 0; i < this.length; i++) {let newVal = callback(this[i])ret.push(newVal)}return ret} We iterate through the array (represented by ), apply the callback function, and push the resulting value onto a new array. And subsequently return that new array. this We could write this more succinctly using our new function. myForEach Array.prototype.myMap = function(callback) {let ret = []this.myForEach(val => ret.push(callback(val)))return ret} Moving on. myFilter By now we’re starting to get the hang of it. Here is the filter call signature. let people = [{ 'name': 'Bob', 'age': 70 },{ 'name': 'Sue', 'age': 30 },{ 'name': 'Joe', 'age': 18 } ] let youngPeople = people.filter( person => person.age < 69 )// returns array with two objects.// [ { 'name': 'Sue', 'age': 30 },// { 'name': 'Joe', 'age': 18 } ] // orconst isYoung = person => person.age < 59let youngPeople = people.filter(isYoung) So the filter expects a callback which returns a or , also referred to as a predicate. The function returns a new array. Based on our experience we can quickly whip this up. true false Array.prototype.myFilter = function(callback) {let ret = []this.myForEach( (val) => {if (callback(val) === true) ret.push(val)}return ret} Pretty straight forward. Note I could have written instead of , but I did this to emphasize that we expect the callback to return or . if (callback(val)) if (callback(val) === true) true false myReduce The reduce function is a little more complex to grok. The example of reduce is to sum elements of an array. This is what it would look like. textbook let arr = [ 1, 2, 3, 4 ] let sum = arr.reduce( (acc, val) => acc + val ) console.log(sum)// prints out 10 The callback takes two arguments, the first one is often referred to as the accumulator, and the second one is the value of a particular item of the array. In this example, the accumulator keeps a running total, and with each iteration over the array, its value is added to the accumulator. And at the end the accumulator contains the value we are trying to get. This is what the function looks like in its most basic form. Array.prototype.myReduce = function (callback) {let retthis.myForEach( val => {if (ret === undefined) ret = valelse ret = callback(ret, val)}return ret} It’s a little trickier than the other higher order functions we defined above. Note how we need to check of is or not. This brings up another point. The JavaScript reduce function lets you specify an initial value. That’s not hard to add to our function. We just add an init parameter to the function definition and set the variable to initially. ret undefined ret init Array.prototype.myReduce = function (callback, init) {let ret = initthis.myForEach( val => {if (ret === undefined) ret = valelse ret = callback(ret, val)}return ret} const sumTwoValues = (a, b) => a + b let sum = arr.myReduce( sumTwoValues , 0 ) // added 0 as an argument for initial value. console.log(sum)// prints 10 Improvements For each of the functions above, we could make it such that we include the index of the array element in the callback signature and make it available in the callback. This should allow us to do the following for example. var arr = [ 1, 2, 3, 4, 5, 6 ] arr.forEach( (val, idx) => { if (idx % 2 === 0) console.log(val) }// prints the value of every other item in the array. arr.map( (val, idx) => idx % 2 === 0 ? val * 2 : val * 3 )// create a new array where every even item has been doubled and every odd item has been trippled arr.map( (val, idx) => idx == 0)// return an array with only the first item The implementation is quite easy. In our myForEach function, we pass the value and the index to the callback. And since we use myForEach in all the other functions, we can easily include the index in the callback call. Array.prototype.myForEach = function(callback) {for (var i = 0; i < this.length; i++) {callback(this[i], i)}} Array.prototype.myMap = function(callback) {let ret = []this.myForEach((val, idx) => ret.push(callback(val, idx)))return ret} Array.prototype.myFilter = function(callback) {let ret = []this.myForEach((val, idx) => { if (callback(val, idx)) ret.push(val)} )return ret} Array.prototype.myReduce = function(callback, init) {let ret = initthis.myForEach( ( val, idx ) => {if (ret === undefined) ret = valelse ret = callback(ret, val, idx)})return ret} One more thing we should do is some error checking. For instance we should make sure that the callback is a function. We should check that the array is not null. Array.prototype.myForEach = function(callback) { for (var i = 0; i < this.length; i++) {callback(this[i], i)}} if (this == null) { throw new TypeError('array is null') } if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function' } Array.prototype.myMap = function(callback) { let ret = []this.myForEach((val, idx) => ret.push(callback(val, idx)))return ret} if (this == null) { throw new TypeError('array is null') } if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function' } Array.prototype.myFilter = function(callback) { let ret = []this.myForEach((val, idx) => { if (callback(val, idx)) ret.push(val)} )return ret} if (this == null) { throw new TypeError('array is null') } if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function' } Array.prototype.myReduce = function(callback, init) { let ret = initthis.myForEach( ( val, idx ) => {if (ret === undefined) ret = valelse ret = callback(ret, val, idx)})return ret} if (this == null) { throw new TypeError('array is null') } if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function' } That’s the end. The actual Javascript , , and functions are a more complex. But by coding this base implementations, you may better understand how they work under the hood. forEach map filter reduce If you’ve enjoyed it, send me some love and click the heart below.