我正在尝试编写一个简单的compose
函数,该函数需要一系列函数,并像这样构成它们:
compose(func1, func2, func3)(n) === func1(func2(func3(n)))
我这样做是通过递归一个rest参数来实现的,
var compose = function(...args) {
return (n) => {
if (args.length) {
return args[0](compose(args.slice(1)));
} else {
return n;
}
};
};
然后,我尝试组成由一系列其他功能组成的新功能,
var plusOneAndTwo = compose((n) => n + 1, (n) => n + 2);
plusOneAndTwo(1);
我没有返回4,而是以字符串的形式返回了compose
内部的内部匿名函数的主体,
"(n) => {
if (args.length) {
return args[0](compose(args.slice(1)));
} else {
return n;
}
}1"
请注意字符串末尾的"1"
!我不知道为什么会这样,尤其是我对如何将1附加到末尾感到困惑。
感谢您的澄清,谢谢!
答案 0 :(得分:3)
问题在递归调用中发生。
特别是,您没有将参数n
传递给它(上面的其他建议)。此外,您需要在调用中扩展rest参数。
您应该使用类似的内容:
return args[0](compose(...args.slice(1))(n))
以您为例,您只是返回:
return args[0](compose(args.slice(1)));
在您的示例中,您呼叫compose((n) => n + 1, (n) => n + 2);
。然后,Compose返回一个以n
作为参数的函数。在此函数中,args.length变为1(即true-is),args [0]变为(n) => n + 1
,而args.slice(1)变为[(n) => n + 2]
。
接下来,您使用参数n = 1
调用此返回的函数。由于args.length为1,因此if()语句将进入if()情况。在这种情况下,它将使用参数compose(args.slice(1))
调用args [0]。
在此递归调用中,将compose(args.slice(1))评估为一个函数,并以n作为参数,并使用相同的函数体。
然后将此函数作为参数n
赋予args [0](在外部调用中)。回想一下,在这种情况下args [0]是函数(n) => n + 1
。
因此整个通话等效于:
// returned from the recursive call to compose(args.slice(1))
var n = (n) => {
if (args.length) {
return args[0](compose(args.slice(1)));
} else {
return n;
}
}
// applied to arg[0] == (n) => n + 1
return n + 1
这意味着代码将尝试添加数字1的函数。 在JavaScript中,添加函数和数字会导致两个对象强制转换为字符串。将数字强制转换为字符串很简单,将函数强制转换为字符串将返回函数源代码。然后添加这些字符串以提供您看到的返回值:函数主体为一个字符串,末尾为1。
答案 1 :(得分:1)
您可以采用其他方法,方法是返回新函数或返回最后一个函数以使用参数进行调用。
const
compose = (...fns) => fns.length
? v => compose(...fns.slice(0, -1))(fns.pop()(v))
: v => v,
fn1 = n => n * 5,
fn2 = n => n + 2,
fn3 = n => n * 7;
console.log(fn1(fn2(fn3(1))));
console.log(compose(fn1, fn2, fn3)(1));