Higher Order Functions ❀️

Higher Order Functions ❀️

[ ].map(), [ ].filter(), [ ].reduce() "WITH POLYFILLS 🀩"

Β·

7 min read

Functions ❀️ are the most beautiful thing in JavaScript and Functional Programming is not possible without Higher Order functions but then... πŸ€”

What are Higher Order functions?

Functions that operate on other functions, either by taking them as argument or by returning them, are known as Higher order function.

map(), filter() and reduce() can be applied on arrays and these are one of the most used and most conf-used higher order functions but not anymore. πŸ˜ƒ

After reading this blog you will get to know:

  • What are Higher Order Functions?
  • What are map(), filter() and reduce()?
  • What's the difference?
  • How to remember the different superpower they have?
  • What is a Polyfill?
  • Appropriate Polyfill for each of them. (Most asked interview Question)

So, let's first understand,

What are Polyfills?

Polyfill is the piece of code to be used in case of browser fallback, or, the logic that would be required if that modern functionality never existed.

Now let's move on to understanding the three most used higher order functions along with their polyfills:

Transforming arrays with map() :

The map function,

  • receives a function containing the transformation logic
  • applies that logic to each and every element of the array (on which map() is applied)
  • returns a new transformed array of the same length.

For example :

const arr = [5,3,2,1,4];
const output = arr.map(x => x*2);
console.log(output);

Output: [10, 6, 4, 2, 8]

const arr = [5,3,2,1,4];
const binary = x => x.toString(2);
const output = arr.map(binary);
console.log(output);

Output: ['101', '11', '10', '1', '100']

Polyfill for map() :

const ourMap = (array, transform) => {
   let mapped = [];
   for(let element of array){
      mapped.push(transform(element));
   }
   return mapped;
}

For Example:

const ourMap = (array, transform) => {
    let mapped = [];
    for(let element of array){
       mapped.push(transform(element));
    }
    return mapped;
 }
const double = x => x*2;
const arr = [5,3,2,1,4];
const output = ourMap(arr, double);
console.log(output)

Output: [10,6,4,2,8]

To use ourMap function directly over an array we can use Array.prototype

Array.prototype.ourMap = function (transform) {
    let mapped = [];
    for(let i =0; i<this.length; i++){
       mapped.push(transform(this[i]));
    }
    return mapped;
 }

This is an exact replacement for map function. 🌟

Note: We replaced the arrow function with traditional function keyword because "this" doesn't works with arrow functions as intended. To know more read my blog which will be posted next week. Stay Tuned!

Let's see an example for this as well:

Array.prototype.ourMap = function (transform) {
    let mapped = [];
    for(let i =0; i<this.length; i++){
       mapped.push(transform(this[i]));
    }
    return mapped;
 }
const double = x => x*2;
const arr = [5,3,2,1,4];
const output = arr.ourMap(double);
console.log(output);

Output: [10,6,4,2,8]

Filtering arrays with filter() :

The filter function,

  • receives a function containing the filtration logic
  • tests each and every element of the array (on which filter() is applied) against the condition mentioned in filtration logic
  • for all the elements that pass the test, a new filtered array of the same or lesser length is returned.

For example :

  • Find the elements lesser than 3 in [5,3,2,1,4]
const arr = [5,3,2,1,4];
const output  = arr.filter(x => x<3);
console.log(output);

Output: [2,1]

  • Find even numbers in [5,3,2,1,4]
const arr = [5,3,2,1,4];
const even = x =>  x%2 === 0;
const output  = arr.filter(even);
console.log(output);

Output: [2,4]

Polyfill for filter() :

const ourFilter = (array, test) => {
   let passed = [];
   for(let element of array){
      if(test(element)){
         passed.push(element)
      }
   }
   return passed;
}

For Example:

const ourFilter = (array, test) => {
   let passed = [];
   for(let element of array){
      if(test(element)){
         passed.push(element)
      }
   }
   return passed;
}
const lessThanThree = x => x<3;
const arr = [5,3,2,1,4];
const output = ourFilter(arr, lessThanThree);
console.log(output)

Output: [2,1]

To use ourFilter function directly over an array we can use Array.prototype

Array.prototype.ourFilter = function (test) {
    let mapped = [];
    for(let i =0; i<this.length; i++){
       mapped.push(test(this[i]));
    }
    return mapped;
 }

ourFilter is now an exact replacement for filter function. 🌟 Let's see an example for better clarity.

Array.prototype.ourFilter = function (test) {
    let mapped = [];
    for(let i =0; i<this.length; i++){
       mapped.push(test(this[i]));
    }
    return mapped;
 }
const lessThanThree = x => x<3;
const arr = [5,3,2,1,4];
const output = arr.ourFilter(lessThanThree);
console.log(output)

Output: [2,1]

Summarizing arrays with reduce() :

Kindly pay attention!
This is a bit different from the above two.

The reduce function may receive 2 values:

  1. A summarizing function that has 2 parameters. (mandatory)
  2. An initial value for the first parameter of the summarizing function. (optional)

If the array consists at least one element the initial value parameter can be skipped and the first element of the array is then by default treated as the initial value.

now, the summarizing function has following 2 parameters:

  1. First one is generally the one that we have to return as a result.
  2. Second one is the iterator that iterates over the array.

The summarizing function runs for all the elements of the array and stores the result in the first parameter. At the end it returns the updated parameter which is returned as the final output of reduce function.

Working of the reduce function can be understood in a better way by following examples:

  • To find the sum of all elements of an array

Solution one (without skipping the optional initialization)

const arr = [5,3,2,1,4];
const output = arr.reduce((sum, current) => sum+=current, 0);
console.log(output);

Output: 15

Solution two (skipping the optional initialization as the array contains at least one element)

const arr = [5,3,2,1,4];
const output = arr.reduce((sum, current) => sum+=current);
console.log(output);

Output: 15

  • To find max element from an array.

Solution one (without skipping the optional initialization)

const arr = [5,3,2,1,4];
const output = arr.reduce((max, current) => {
   if(current>max){
      max = current;
   }
return max;
}, arr[0]);
console.log(output);

Output: 5

Solution two (skipping the optional initialization as the array contains at least one element)

const arr = [5,3,2,1,4];
const output = arr.reduce((max, current) => {
   if(current>max){
      max = current;
   }
return max;
});
console.log(output);

Output: 5

Polyfill for reduce() :

const ourReduce = (array, summarize, start) => {
   let result = start === undefined ? array[0] : start;
   for(element of array){
      result = summarize(result, element);
   }
   return result;
}

For Example:

const ourReduce = (array, summarize, start) => {
   let result = start === undefined ? array[0] : start;
   for(element of array){
      result = summarize(result, element);
   }
   return result;
}
const arr = [5,3,2,1,4];
const combine = (a,b) => a+b;
const output = ourReduce(arr, combine, 0);
console.log(output);

Output: 15

To use it directly on an array we can use Array.prototype.

Array.prototype.ourReduce = function (summarize, start) {
   let result = start === undefined? this[0] : start;
   for(let i = 0; i< this.length; i++){
      result = summarize(result, this[i]);
   }
   return result;
}

ourReduce is now an exact replacement for reduce function. 🌟 Let's see an example:

Array.prototype.ourReduce = function (summarize, start) {
   let result = start === undefined? this[0] : start;
   for(let i = 0; i< this.length; i++){
      result = summarize(result, this[i]);
   }
   return result;
}

const arr = [5,3,2,1,4];
const greatestElement = (max, current) => {
   if(current>max){
      max = current;
   }
return max;
}
const output = arr.ourReduce(greatestElement);
console.log(output);

Output: 5

How to remember the different superpower they have?

To remember their superpower πŸš€ just remember that we :

Transform with map()

Filtration with filter()

Summarize with reduce()

Furthermore, their difference may help you remember it better.

map() vs. filter() vs. reduce() :

  1. map() returns an array of same length
    filter() returns an array of same or lesser length
    reduce() returns a single result, not generally an array.

  2. map() receives a single argument
    filter() receives a single argument
    reduce() receives two arguments

I hope the concepts are far better clear now. Thankyou so much and congratulations if you made it till here. Here is a thought for the day as a present🎁.

TFTD:

"People usually have a very acute sense of how fast time passes and its finitude existence. Don't take it for granted. For every second that you get with your family members/loved ones, cherish them and be grateful for them."

Love & Regards,
Vinamra Jain

Β