DEV Community

Rahul Ranjan
Rahul Ranjan

Posted on

Function Composition In JavaScript with multiple parameters

Function composition in JavaScript is process of combining several function calls into one function.

Ways in which function composition can be done

  1. Creating a high-order function and pass the necessary functions as parameters in this method.
  2. Using reduce() or reduceright() function and pass all the independent functions that needs to be combined.

Let's see how can this be done

Approach 1 : Using higher order functions

UseCase: If we have a scenario where we need to print details of employee on some kind of employee card for each employee and we have three independent functions.
Code for the example is written below


    // function1 to print employee id
    const printId = (employeeId) =>{
      console.log("Printing| EmployeeId:", employeeId);
    }

    //function2 to print employee name
    function printname(name) {
      console.log("Printing| Name:", name);
    }

    //function3 to print email and designation among other info.
    const printOther = (email, designation) =>{
      console.log(`Printing| Email: ${email} ,Designation: ${designation}`);  
    }

    //function 4 is an higher order function that runs the functions being passed into it
    const print = (funcA, funcB) => (param_ToFunctionB) =>
      funcA(funcB(param_ToFunctionB));


    //printing the combination of above js functions
    print(
      printId(1234),
      print(
        printname("Rahul"),
        printOther("rahul@web.com", "software engineer")
      )
    );

    //output
    Printing| EmployeeId: 1234
    Printing| Name: Rahul
    Printing| Email: rahul@web.com ,Designation: software engineer


Enter fullscreen mode Exit fullscreen mode

the print(funcA, funcB) function takes a bigger form .i.e. more lines of code when we need to add more functions to the composition.

Approach 2: Using reduce() or reduceRight() functions for function composition

For same use case as above , second way of doing function composition in JavaScript is by using reduce() or reduceRight() functions.

JavaScript reduceRight() function runs a function on each element of the array to reduce it into a single value. Also , reduceRight() function executes elements from the right, whereas reduce() method executes elements from left.

It is noteworthy that functions objects being passed to the reduce() or reduceRight() function should have same number of arguments in each of them, and it should also return one value
So, any function can be made composable by converting that function into a curry function

Currying is the technique in functional way of programming of transforming a function taking multiple input arguments (two, three or more- polyadic) into set of internally related functions by using closures, where each function is single input, single output function, and final output returned from the outermost function.

Simply written, currying is the way of reshaping the function type f(a, b, c) to f(a)(b)(c) .
e.g.

    //normal function call
    const departmentEmployees=(departmentName,empId,empName)=>{
        console.log(`${departmentName} Info| ${empId} :: ${empName}`);
        return true;
    }
    //transformed carried function
    const departmentCarryTransformed = (departmentName)=>(empId)=>(empName)=>{
        console.log(`${departmentName} Info | ${empId} :: ${empName}`);
            return true;
    }
    //carry function benefit
    //we can create single global variable for a department and use it elsewhere across the file or the page
    let accountsDepartment= departmentCarryTransformed("Accounts");
    accountsDepartment(123)('bob');
    accountsDepartment(2)('tom');


Enter fullscreen mode Exit fullscreen mode

So, functions in this case

    // function1 to print employee id
    const printId = (attributes) => {
      console.log("Printing| EmployeeId:", attributes.employeeId);
      return attributes;
    };

    //function2 to print employee name
    function printname(obj) {
      console.log("Printing| Name:", obj?.name);
      return obj;
    }


    //function3 to print email and designation among other info.
    const printOther = (attributes) => {
      console.log(
        `Printing| Email: ${attributes?.email} ,Designation: ${attributes?.designation}`
      );
    };


    // TO make the function composition easier, we can use rest parameters to pass indefinite number of arguments to the function
    const smarterPrint =
      (...functions) =>
      (params) =>    functions.reduceRight((p, fn) => fn(p),params);


    // parameters that we need to pass to different functions to print specific info
    const fn_params = {
      employeeId: 1234,
      name: "rahul ranjan",
      email: "rahul@web.com",
      designation: "software engineer",
    };

    // this function composition way takes lesser code of lines.
    smarterPrint(printOther, printname, printId)(fn_params);

    // second way
    const smarterPrintOtherWay = (paramsObj) => printOther(printname(printId(paramsObj)));

    smarterPrintOtherWay(fn_params);

    //output is same 
    Printing| EmployeeId: 1234
    Printing| Name: Rahul
    Printing| Email: rahul@web.com ,Designation: software engineer


Enter fullscreen mode Exit fullscreen mode

The benefit of this approach for function composition is visually seen as our code base increases.

References

Top comments (0)