JavaScript 函数分别返回 False 和 0

1 javascript functional-programming

我是 JavaScript 的新手,我正在尝试编写函数式编程来计算一个数字是否为奇数 (isOdd)。我不明白为什么当我连续两次调用 isOdd() 时会得到 true 和 0 或 false 和 1。

这是我的代码:

var mod = m => {return number => {return number % m }}
var eq = number1 => {return number2 => {return number1 === number2}}
var combine = (...fns) => { return arg => {for(let fn of fns.reverse()) arg = fn(arg); return arg;}}

var eq1 = eq(1)
var mod2 = mod(2)
var isOdd = combine(eq1, mod2)

mod2(4) -----> returns 0
mod2(3) -----> returns 1
eq1(1)  -----> returns true
eq1(2)  -----> returns false

isOdd(1) returns true
isOdd(1) returns 1 (what??)
Run Code Online (Sandbox Code Playgroud)

我无法理解我错过了什么或出了什么问题。我在大多数浏览器中测试了这段代码。

不胜感激,如果有人可以详细解释。

我可以再次包装 isOdd 并有类似的东西

isOdd = (number) => {return Boolean(combine(eq1, mod2))}
Run Code Online (Sandbox Code Playgroud)

每次都返回布尔值。但我想首先了解我错过了什么/

Seb*_*mon 5

Array.prototype.reversefns原地反转数组。你打电话.reversefns ,每次你打电话isOdd,即使你在传递功能的固定参数列表combine 一次。该列表combine在每次调用isOdd(1).

换句话说,您的第一次isOdd(1)调用会记住fns原始combine(eq1, mod2)调用的数组。fns[ eq1, mod2 ]。然后你调用fns.reverse()迭代它;但这会变异 fns[ mod2, eq1 ]. 你得到了正确的结果,因为你想以相反的顺序调用函数。结果调用是eq1(mod2(1)) === eq1(1) === true

在你的第二个isOdd(1)电话,然而,fns仍然记得,它仍然具有反转的[ mod2, eq1 ]价值,因为它的范围combine,那么另一个isOdd调用不会重置最初传递fns。第二个isOdd调用再次反转这个数组因为fns.reverseisOdd. 结果调用是mod2(eq1(1)) === mod2(true) === 1(因为true % 2被强制转换为1 % 2)。

一个工作函数看起来像这样:

const combine = (...fns) => {
    const reversedFns = fns.reverse();

    return (arg) => {
      for(let fn of reversedFns){
        arg = fn(arg);
      }
  
      return arg;
    };
  };
Run Code Online (Sandbox Code Playgroud)

一种更简单的方法使用Array.prototype.reduceRight

const combine = (...fns) => (arg) => fns.reduceRight((result, fn) => fn(result), arg);
Run Code Online (Sandbox Code Playgroud)

由于您想根据从右到左的列表将多个操作聚合到单个结果中,因此reduceRight这是一个完美的方法。您从 开始arg,从右到左遍历函数列表,然后用 调用当前函数arg,这将成为arg下一个函数的新函数。返回最终结果。所有这些都被代码捕获fns.reduceRight((result, fn) => fn(result), arg)