我是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??)
我不明白自己错过了什么或出了什么问题。我在大多数浏览器中测试了此代码。
欣赏是否有人可以详细解释。
我可以再次包装isOdd并得到类似
isOdd = (number) => {return Boolean(combine(eq1, mod2))}
每次都会返回布尔值。但是我想了解我最想念的东西/
Array.prototype.reverse
fns
就地反转数组。你打电话.reverse
的fns
,每次你打电话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.reverse
被调用了isOdd
。产生的呼叫是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;
};
};
一个更简单的方法是Array.prototype.reduceRight
:
const combine = (...fns) => (arg) => fns.reduceRight((result, fn) => fn(result), arg);
由于您要基于从右到左的列表将多个操作聚合到单个结果上,因此reduceRight
是一种理想的方法。您从开始arg
,从右到左浏览功能列表,然后使用调用当前功能arg
,这将成为arg
下一个功能的新功能。返回最终结果。所有这些都由代码捕获fns.reduceRight((result, fn) => fn(result), arg)
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句