![](/img/trans.png)
[英]How Array.reduce put functions as parameters in function composition?
[英]How Javascript `reduce` performed on function array achieves function composition?
我在redux
compose
功能中遇到了这种模式。 我仍然不明白如何在下面的示例中从最后开始而不是从第一个开始评估函数:
function f2(a) {
return a + a;
}
function f3(a) {
return a + a + a;
}
function f4(a) {
return a + a + a + a;
}
function f5(a) {
return a + a + a + a + a;
}
function compose(...funcs) {
return funcs.reduce(function x(a, b) {
return function y(...args) {
const temp = a(b(...args));
return temp;
};
});
}
const composedFunction = compose(f2, f3, f4, f5);
const result = composedFunction(2);
在第一个reduce
迭代中,累加器为f2
因此我们得到f2(f3(2))=12
。 在下一次迭代中,我们将调用f4(12)=48
。 在上一次迭代中,我们将调用f5(48)=240
。 因此,评估顺序为f5(f4(f2(f3(2))))
。 但是使用console.log
我看到评估顺序是f2(f3(f4(f5(2))))
,巧合的也是240。
据我了解,函数y
是为所有数组元素调用的,那么为什么只有最后一个函数将2
作为参数?
让我们通过一个非常简单的示例逐步完成代码:
compose(f2, f3, f4)
由于没有传递任何初始值来减少值,因此它将以数组的第一个(f2)和第二个(f3)值开头,并以该值调用回调, x
的调用为a
为f2
, b
为f3
。 现在x
不执行任何操作,只返回可以通过闭包访问a和b的函数y
。
Reduce现在将继续到第三个元素,第一个参数是上一个回调(闭包y
)的结果,第二个参数是f4
。 现在再次调用x
,并在y
上创建另一个闭包, y
从整个函数中最终返回。
如果我们尝试可视化这样的闭包函数,它将是:
y { // closure of y
a -> y { // a references another closure of y
a -> f3,
b -> f2
},
b -> f4
}
现在,您调用该闭包y
并将2传递给它,这将调用b
( f4
)并将结果传递给该调用到a
(闭包y)。
a ( b(...args))
y { ... } ( f4(2) )
现在,封闭的y将执行相同的操作:
a ( b ( ...args))
f2( f3( f4( 2 ) ) )
提示:有时很难跟踪闭包的值,因此控制台为您提供了强大的实用程序来跟踪它们:在控制台的“ debugger”选项卡中打开代码,单击函数调用所在的行号。附加断点,然后再次运行代码,只要到达断点,执行就会产生,您可以看到所有变量(包括封闭变量)的值。
reduce不会调用函数f2,f3,f3,f5,而是从这些函数创建函数。 这是每次迭代中累加器的值。 请注意,该值是一个function
而不是function
执行的结果。
1:a = f2; b = f3;返回值(不是温度,但函数y)= f2(f3(... args))
2:a(上一个返回值)= f2(f3(... args)); b = f4;返回值= f2(f3(f4(... args))))
等等....
撰写功能可以重写为:
function compose(...funcs) {
return funcs.reduce(function (a, b) {
return function (arg) {
const temp = a(b(arg));
return temp;
};
});
}
第一次迭代后,作为下一个累加器传递的返回函数为:
function (arg) { // R1
return f2(f3(arg));
}
在第二次迭代之后,作为下一个累加器传递的返回函数为:
function (arg) { // R2
return R1(f4(arg));
}
最后,分配给compositionFunction的返回函数为:
function (arg) { // composedFunction
return R2(f5(arg));
}
因此,运行composedFunction(2)
并返回上链:
f5(2) returns 10
R2(10) returns R1(f4(10))
which is R1(40)
R1(40) returns f2(f3(40))
which is f2(120)
which is 240
希望这足够了。
可以将其写为以下单个调用:
function composedFunction(arg) {
return f2(f3(f4(f5(arg))));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.