使用reduceRight()的具有多个参数的函数组合-JavaScript

时间:2019-05-13 22:03:00

标签: javascript

我正在尝试使用reduceRight实现具有多个参数的函数组合。这个问题link已得到解答,但输入数据略有不同。由于某种原因,我收到以下错误:Uncaught TypeError: fn is not a function。避免以这种格式使用func3 = ([x, y]) => (y > 0 ? x + 3 : x - 3);。让我知道是否有解决方法。

 const compose = (...fns) => (...args) =>
      fns.reduceRight((acc, fn) => fn(acc), args);

    const func3 = (x, y) => (y > 0 ? x + 3 : x - 3);
  //const func3 = ([x, y]) => (y > 0 ? x + 3 : x - 3); - avoid using this version

    const func2 = x => x ** 2;

    const func1 = x => x - 8;

    const fnOne = compose([func1, func2, func3])('3', 1);
    console.log(fnOne); // should be 1081

    const fnTwo = compose([func1, func2, func3])('3', -1);
    console.log(fnTwo); //should be -8


  [1]: https://stackoverflow.com/questions/55842990/multiple-arguments-composible-function-implementation-using-reduceright

解决方案

Array#reduceRight仅支持一个currentValue,因此我们不能使函数接受多个参数。唯一的方法是通过从数组中弹出并手动调用它来避免对第一次调用使用reduceRight,而不是让reduceRight做到:

第一种方法

const compose = fns => (...args) =>
      fns.reduceRight((acc, fn) => fn(acc), fns.pop()(...args));

第二种方法

const compose = fns => (...args) =>
      fns.reduceRight((acc, fn) => fn(...[acc, ...args.slice(1)]), args[0]);

3 个答案:

答案 0 :(得分:2)

您要将数组传递给compose而不是一个函数(或多个函数),所以fn是一个数组,当您尝试将其用作函数时会收到该错误。

可以将...fns替换为fns(这样compose会期望有一个数组),或者在调用compose时删除方括号。还要使用已注释掉的func3版本:

const compose = (...fns) => (...args) =>
      fns.reduceRight((acc, fn) => fn(acc), args);

const func3 = ([x, y]) => (y > 0 ? x + 3 : x - 3);

const func2 = x => x ** 2;

const func1 = x => x - 8;

const fnOne = compose(func1, func2, func3)('3', 1);
console.log(fnOne); // should be 1081

const fnTwo = compose(func1, func2, func3)('3', -1);
console.log(fnTwo); //should be -8

答案 1 :(得分:0)

  1. 您需要提供函数以组成三个参数/函数而不是数组。
  2. func3将是第一个执行的函数,因此它将接收数组args。该数组的x和y变量必须为destructure。可以在参数定义中进行这种减少,例如:([x,y])。

const compose = (...fns) => (...args) =>
fns.reduceRight((acc, fn) => fn(acc), args);

const func3 = ([x, y]) => y > 0 ? x + 3 : x - 3;

const func2 = x => x ** 2;

const func1 = x => x - 8;

const fnOne = compose(func1, func2, func3)('3', 1);
console.log(fnOne); // should be 1081

const fnTwo = compose(func1, func2, func3)('3', -1);
console.log(fnTwo); //should be -8

答案 2 :(得分:0)

如果不能,或者想将func3转换为单个参数函数。您可以在调用args时传播fn。然后将结果捕获到数组中,以便可以将其分散到下一个fn调用中。返回最终结果时,只需获取结果数组的第一个元素。

const compose = (...fns) => (...args) =>
  fns.reduceRight((args, fn) => [fn(...args)], args)[0];

const func3 = (x, y) => (y > 0 ? x + 3 : x - 3);
// const func3 = ([x, y]) => (y > 0 ? x + 3 : x - 3); - avoid using this version

const func2 = x => x ** 2;
const func1 = x => x - 8;

const fnOne = compose(func1, func2, func3)('3', 1);
console.log(fnOne); // should be 1081

const fnTwo = compose(func1, func2, func3)('3', -1);
console.log(fnTwo); //should be -8