JavaScript中基于Currying和reduce的compose函数执行逻辑及输出疑问
控制台输出80、88、90的原因
你用到的compose是函数组合工具,核心规则是传入的函数从右到左依次执行,前一个函数的返回值作为后一个函数的入参。
你调用compose时传入的函数顺序为:log → addTransactionFee → log → addTax → log → addMonthlyPromotion
按照从右到左的执行规则,实际运行顺序为:addMonthlyPromotion → log → addTax → log → addTransactionFee → log
初始传入的计算基数是100,每一步计算过程如下:
- 第一步:
addMonthlyPromotion(100)= 100 * 0.8 = 80,返回值传给下一个函数log - 第二步:
log(80)打印80,返回80给下一个函数addTax - 第三步:
addTax(80)= 80 * 1.1 = 88,返回值传给下一个函数log - 第四步:
log(88)打印88,返回88给下一个函数addTransactionFee - 第五步:
addTransactionFee(88)= 88 + 2 = 90,返回值传给下一个函数log - 第六步:
log(90)打印90,返回90赋值给paymentAmount
所以控制台会依次输出80、88、90三个值。
基于reduce实现的compose函数执行流程详解
首先看compose的定义:
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
我们把你传入的6个函数按顺序记为数组:fns = [log, addTransactionFee, log, addTax, log, addMonthlyPromotion]
这里的reduce没有传入初始值,所以会从数组第一个元素开始迭代,每一轮迭代都返回一个新的组合函数,完整迭代过程如下:
- 第一轮迭代:
- 初始
f为数组第一个元素log,g为数组第二个元素addTransactionFee - 返回新函数
fn1 = (...args) => log(addTransactionFee(...args))
- 初始
- 第二轮迭代:
f为上一轮返回的fn1,g为数组第三个元素log- 返回新函数
fn2 = (...args) => fn1(log(...args)) = (...args) => log(addTransactionFee(log(...args)))
- 第三轮迭代:
f为上一轮返回的fn2,g为数组第四个元素addTax- 返回新函数
fn3 = (...args) => fn2(addTax(...args)) = (...args) => log(addTransactionFee(log(addTax(...args))))
- 第四轮迭代:
f为上一轮返回的fn3,g为数组第五个元素log- 返回新函数
fn4 = (...args) => fn3(log(...args)) = (...args) => log(addTransactionFee(log(addTax(log(...args)))))
- 第五轮迭代:
f为上一轮返回的fn4,g为数组第六个元素addMonthlyPromotion- 返回最终的组合函数
finalFn = (...args) => fn4(addMonthlyPromotion(...args)) = (...args) => log(addTransactionFee(log(addTax(log(addMonthlyPromotion(...args))))))
当你调用compose(xxx)(100)时,本质就是执行finalFn(100),函数会从最内层的addMonthlyPromotion开始执行,一层层向外传递参数,最终得到计算结果,和前面的输出逻辑完全一致。
内容的提问来源于stack exchange,提问作者Rakibul hasan
相关产品推荐
相关产品推荐

