Creating Custom Higher Order Functions

And Why Functions are first class citizens in Javascript

·

3 min read

Hi There,

In my previous Map function in Javascript blog post I mentioned, I will make a blog post about how to define our custom map function. Today we are going to do more :) Creating custom map/forEach/filter/reduce higher order functions(HOC from now on) is a great way to understand/solidify how things work under the hood.

pankaj-patel-_SgRNwAVNKw-unsplash.jpg

Let us see the code. Comments are added for clarification purposes.

  • Custom Map Function
//Guard clause to avoid collision with 3 party software or ESNext versions
if(!Array.prototype.customMap){
    Array.prototype.customMap = function(callback){
        const result = [];       
        for(let i = 0 ; i< this.length ; i++){
            //Passing array current element,index and original array
           //itself in every callback 
            const itemResult = callback.call(null,this[i],i,this);    
            result.push(itemResult);
        }
        return result;
    }

}

const numbers = [1,2,3,4,5];
const mappedNumbers = numbers.customMap((num,idx,arr) => {
    console.log(`Num= ${num}, Index = ${idx}`);
    console.log("Original Array: ",arr);
    return num * (idx + 1);
})

console.log("Mapped Numbers:",mappedNumbers); 
/* -> 
Num= 1, Index = 0
Original Array:  (5) [1, 2, 3, 4, 5]

Num= 2, Index = 1
Original Array:  (5) [1, 2, 3, 4, 5]

Num= 3, Index = 2
Original Array:  (5) [1, 2, 3, 4, 5]

Num= 4, Index = 3
Original Array:  (5) [1, 2, 3, 4, 5]

Num= 5, Index = 4
Original Array:  (5) [1, 2, 3, 4, 5]

Mapped Numbers: (5) [1, 4, 9, 16, 25]
*/
  • Custom ForEach Function

Since there is no need to return a value from forEach we just call our callback with current item, index and original array respectively .

if(!Array.prototype.customForEach){
    Array.prototype.customForEach = function(callback){            
        for(let i = 0 ; i< this.length ; i++){           
            callback.call(null,this[i],i,this) 
        }
    }
}

const numbers = [1,2,3,4,5];
numbers.customForEach(num => console.log(num ** 2)); // -> 1,4,9,16,25
  • Custom Filter Function
if(!Array.prototype.customFilter){
    Array.prototype.customFilter = function(callback){
        const result = [];
        for(let i = 0 ; i< this.length ; i++){
            //If current item satisfies the criteria(callback result)
            // add it to the result array
            const itemShouldAdd = callback.call(null,this[i],i,this);
            if(itemShouldAdd){
                result.push(this[i]);    
            }             
        }
        return result;
    }
}

const numbers = [1,2,3,4,5];
const evenNumbers = numbers.customFilter(num => num % 2 === 0);
console.log(evenNumbers); // -> [2,4]
  • Custom Reduce Function
if(!Array.prototype.customReduce){
    Array.prototype.customReduce = function(callback,initialValue = undefined){
        //if initial value provided for our reduce function
        //take it as accumulator initial value(startIndex = 0), otherwise
       //assign array first value to accumulator value(startIndex = 1)
        let accumulatorValue = initialValue == undefined ? this[0] : initialValue;
        const startIndex = initialValue == undefined ? 1 : 0;
        for(let i = startIndex ; i< this.length ; i++){
              accumulatorValue = callback.call(null,accumulatorValue,this[i],i,this);          
        }
        return accumulatorValue;
    }
}

const numbers = [1,2,3,4,5];
console.log(numbers.customReduce((acc,num) => acc * num, 5)); // -> 600

As you see we can easily managed to implement these functions by ourselves. If you have anything to add/edit please do not hesitate to share/comment.

You can also get these code snippets from github.

Stay tuned, bye bye.

Did you find this article valuable?

Support Chety's Blog by becoming a sponsor. Any amount is appreciated!