Композиция функций в JavaScript с несколькими параметрами

Композиция функций в JavaScript — это процесс объединения нескольких вызовов функций в одну функцию.

Способы, с помощью которых может быть выполнена композиция функций

  1. Создание функции высокого порядка и передача необходимых функций в качестве параметров в этот метод.
  2. Использование функции reduce() или reduceright() и передача всех независимых функций, которые необходимо объединить.

Давайте посмотрим, как это можно сделать

Подход 1: Использование функций более высокого порядка

UseCase: Если у нас есть сценарий, в котором нам нужно распечатать данные о сотруднике на некоторой карточке сотрудника для каждого сотрудника, и у нас есть три независимые функции.
Код для примера приведен ниже


    // 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


Вход в полноэкранный режим Выйти из полноэкранного режима

функция print(funcA, funcB) принимает более объемную форму .т.е. больше строк кода, когда нам нужно добавить больше функций в композицию.

Подход 2: Использование функций reduce() или reduceRight() для композиции функций

Для того же случая использования, что и выше, второй способ выполнения композиции функций в JavaScript — использование функций reduce() или reduceRight().

Функция JavaScript reduceRight() выполняет функцию на каждом элементе массива, чтобы уменьшить его до одного значения. Кроме того, функция reduceRight() выполняет элементы справа, в то время как метод reduce() выполняет элементы слева.

Примечательно, что объекты функций, передаваемые функции reduce() или reduceRight(), должны иметь одинаковое количество аргументов в каждом из них, а также возвращать одно значение.
Таким образом, любую функцию можно сделать композиционной, преобразовав ее в функцию карри.

Карри — это техника в функциональном программировании, позволяющая преобразовать функцию, принимающую множество входных аргументов (два, три или более — полиадические), в набор внутренне связанных функций с помощью замыканий, где каждая функция является единственной входной, единственной выходной функцией, а конечный выход возвращается из самой внешней функции.

Проще говоря, замыкание — это способ преобразования типа функции f(a, b, c) в f(a)(b)(c).
например.

    //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');


Войти в полноэкранный режим Выйти из полноэкранного режима

Таким образом, функции в данном случае

    // 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


Войти в полноэкранный режим Выйти из полноэкранного режима

Преимущество такого подхода к композиции функций наглядно видно по мере увеличения нашей кодовой базы.

Ссылки

  • https://javascript.info/currying-partials
  • https://jrsinclair.com/articles/2022/javascript-function-composition-whats-the-big-deal/
  • https://medium.com/hackernoon/javascript-functional-composition-for-every-day-use-22421ef65a10

Оцените статью
Procodings.ru
Добавить комментарий