返回函数时,reduce函数如何工作?还想进一步了解组成和构图

问题描述

以下代码功能方式编写。有一个要购买的用户对象。过程如下:将商品添加到购物车,添加税款,购买该商品并将其推送到用户的购买历史记录数组中。然后,最后将原来的购物车清空。这全部通过使用reduce函数来完成,该函数具有一个compose函数

我要努力理解的是在这种情况下reduce函数是如何工作的。根据我的理解,compose函数是作为reduce的回调函数传递的。组成函数中的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,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',cart: [ { name: 'laptop',price: 244 } ],purchases: [] }  

我试图映射f和g元素的流。我知道f可以容纳compose函数返回的任何值,但是为什么初始值是匿名函数。此外,为什么item元素从数组中的最后一个元素开始并向后工作?我也对为什么emptyCart函数在reduce的最后一个循环中变为f值感到困惑。如果有人可以向我解释这一点,我将非常感激。谢谢。

解决方法

您的日志未正确映射执行流程。

您首先登录f,然后登录g,但是对于f(g(x))g首先被评估,然后是ff(g(x)可以读作“ x of g之后的f”或“ x of g of 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'));