7.1 C
Pakistan
Monday, February 26, 2024

JavaScript Higher Order Functions

Functions that interact with other functions are referred to as higher order functions.

These are functions that either return functions or accept functions as arguments.

It’s possible that you frequently use them without realizing what their conceptual name is.

Using higher order functions results in code that is clear, simple, and functional.

They enable us to encapsulate repeatable logic in functions that are simple to test and abstract it away.

Starting with a basic data structure:

const cart = [
  { name: 'Lemonade', price: 299 },
  { name: 'Coffee', price: 399 },
  { name: 'Water', price: 199 }
];

We will illustrate both types of higher order functions from this point on.

The first is a function that takes an argument from another function.

Easy. Let’s use Array.prototype.reduce:

const cart = [
  { name: 'Lemonade', price: 299 },
  { name: 'Coffee', price: 399 },
  { name: 'Water', price: 199 }
];

const total = cart.reduce((prev, next) => prev + next.price, 0);

console.log(total); // 897

In JavaScript, functions are data types just like any other and can be passed around in the same way as variables.

“A function that returns a function” is the additional attribute of a higher order function. Given how simple it is to pass a function as an argument, this is the more advanced one and most likely the one you’ll use.

This can be used in a composition style to make simple and dependable abstraction layers in functional programming.

Let’s start by making a fast add to cart function:

function addToCart(drink) {
  cart.push(drink);
}

This is excellent; it is clear, uncomplicated, and testable. However, how might we incorporate it into another abstraction?

Savings! A rather typical use case

On the way into the addToCart call, we could multiply by 0.6 to offer a 40% discount:

function addToCart(drink) {
  cart.push(drink);
}

const drink = { name: 'Lemonade', price: 299 };
const price = drink.price * 0.6; // apply discount
addToCart({ ...drink, price }); // set the new price, add to cart

This method works, but it also makes us prone to making easy mistakes, repeating reasoning without actually adhering to any kind of structure or pattern.

Let’s introduce the higher order function, which gives us a function back.

function addToCart(drink) {
  cart.push(drink);
}

function addToCartWithDiscount(amount) {
  return function(drink) {
    const price = drink.price * amount;
    addToCart({... drink, price });
  };
}

Here, we’re intercepting the price property as it enters the addToCart function and multiplying it by the percentage of the discount.

It becomes dynamic as a result, making composition possible.

Let’s create a reusable function that offers a 40% discount on all purchases.

That function returns a new function upon call, which we designate to a variable for future use:

function addToCartWithDiscount(amount) {
  return function(drink) {
    const price = drink.price * amount;
    addToCart({... drink, price });
  };
}

// call our function and apply 40% discount
const addToCartWith40Discount = addToCartWithDiscount(0.6);
// object to pass to cart
const drink = { name: 'Lemonade', price: 299 };
// automatically apply 40% discount with a function call
addToCartWith40Discount(drink);

Take note of how there aren’t any erratic variables or computations that could go wrong.

Here is where things get juicy, so pay attention.

We can now set up additional higher order functions to carry out a single task for us:

function addToCartWithDiscount(amount) {
  return function(drink) {
    const price = drink.price * amount;
    addToCart({... drink, price });
  };
}

const addToCartWith20Discount = addToCartWithDiscount(0.8); // πŸ’° 20%
const addToCartWith40Discount = addToCartWithDiscount(0.6); // πŸ’° 40%
const addToCartWith60Discount = addToCartWithDiscount(0.4); // πŸ’° 60%
const addToCartWith80Discount = addToCartWithDiscount(0.2); // πŸ’° 80%

And utilize them wherever and however we please:

const drink = { name: 'Lemonade', price: 299 };

addToCartWith40Discount(drink); // πŸ’° 40% off

console.log(cart); // βœ… { name: 'Lemonade', price: 179.4 }

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles