以下代码是以函数方式编写的。有一个用户对象要进行购买。流程如下:将商品添加到购物车中,添加税款,购买该商品并将其推送到用户的购买历史数组中。然后最后清空原来的推车。这一切都是通过使用reduce函数来完成的,该函数中传递了一个compose函数
我很难理解reduce函数在这种情况下是如何工作的。根据我的理解,compose函数是作为reduce的回调函数传入的。在compose函数中,f表示累加器,g表示数组中的一个项。
const user = {
name: 'Kim',
active: true,
cart: [],
purchases: []
}
const compose = (f,g) => (...args) => {
console.log(1, f);
console.log(2, g);
return f(g(...args));
}
// The below code is commented out so that I can visualize it in a more simple manner
//purchaseItem (
// emptyCart,
// buyItems,
//applyTaxToItems,
// addItemToCart
//)(user, {name: 'laptop', price: 244});
function purchaseItem(...fns) {
console.log(fns);
return fns.reduce(compose);
}
// Here is each piece broken down to be passed into reduce and the arguments the compose function takes
console.log([emptyCart , buyItems, applyTaxToItems, addItemToCart].reduce(compose)(user, {name: 'laptop', price: 244}));
function addItemToCart(user, item) {
const updateCart = user.cart.concat(item);
return Object.assign({}, user, { cart: updateCart });
}
function applyTaxToItems(user, item) {
return user
}
function buyItems(user, item) {
return user
}
function emptyCart(user, item) {
return user
}
输出如下:
1 [Function]
2 [Function: addItemToCart]
1 [Function]
2 [Function: applyTaxToItems]
1 [Function: emptyCart]
2 [Function: buyItems]
{ name: 'Kim',
active: true,
cart: [ { name: 'laptop', price: 244 } ],
purchases: [] }
我试图绘制f和g元素的流动图。我知道f将保持compose函数返回的任何值,但为什么初始值是匿名函数。此外,为什么item元素从数组中的最后一个元素开始并向后工作?我也很困惑为什么emptyArt函数在reduce的最后一个循环中变成f值。如果有人能向我解释这一点,我将不胜感激。非常感谢。
您的日志没有正确映射执行流。
您首先记录f
,其次记录g
,但对于f(g(x))
,首先计算g
,其次计算f
。CCD_ 6可以被读取";f在x〃的g之后;或";x〃的g的f;。
同样,当您使用类似f(g(...x))
的缩减器来缩减函数数组时,它们将以相反的顺序进行计算,因为您得到的函数的行为类似f(g(h(x)))
。
有关详细说明,请参阅下面的代码。compose2
与您的compose
功能相同,但具有更繁重的日志记录。
如果你运行下面的代码,你可能会更好地了解发生了什么。为了评估由归约/组合创建的函数,我们评估了形式为f(g(...args))
的多个函数。
注意g(...args)
的结果是如何在最终结果向下传播之前全部向上传播的。
const compose2 = (f, g, i) => {
const name = `${f.name} after ${g.name}`;
const h = {[name]: (...args) => {
console.log(i, 'f:', f.name);
console.log(i, 'g:', g.name);
console.log(i, 'args to g:', ...args);
console.log(i, 'g(...args):', g(...args));
console.log(' ');
const res = f(g(...args));
console.log(i, 'result:', res);
return res;
}}[name];
return h;
}
const f_xe = x => x + 'e',
f_xd = x => x + 'd',
f_xc = x => x + 'c',
f_xy = (x, y) => x + y;
console.log([f_xe, f_xd, f_xc, f_xy].reduce(compose2)('a','b'));