Javascript 几个小的减少和一个大的减少?

Javascript 几个小的减少和一个大的减少?,javascript,arrays,typescript,flowtype,Javascript,Arrays,Typescript,Flowtype,使用reduce: addSales(sales: Sale[]) { this.total += sales.reduce((ac, sale) => ac + sale.total, 0); this.tax += sales.reduce((ac, sale) => ac + sale.tax, 0); this.discount += sales.reduce((ac, sale) => ac + sale.discount, 0); this.qty

使用
reduce

addSales(sales: Sale[]) {
  this.total += sales.reduce((ac, sale) => ac + sale.total, 0);
  this.tax += sales.reduce((ac, sale) => ac + sale.tax, 0);
  this.discount += sales.reduce((ac, sale) => ac + sale.discount, 0);
  this.qty += sales.reduce((ac, sale) => ac + sale.qty, 0);
}
使用
.forEach

addSales(sales: Sale[]) {
  sales.forEach(sale => {
    this.total += sale.total;
    this.tax += sale.tax;
    this.discount += sale.discount;
    this.qty += sale.qty;
  });
}
在这里使用
.forEach
似乎更具可读性,而且性能可能更好,因为它只会在其中循环一次

但从长远来看,它是否会降低模块化程度?我的代码中有一些部分是从较小的
.forEach
块开始的,但随着时间的推移,它的大小逐渐增大,并且不知何故难以重构,因为它们彼此“绑定”在一起


你能分享一下你在这方面的经验吗?

在这里使用
forEach
没有什么错,而且肯定比多次调用
reduce
效率更高(尽管程度可以忽略不计,除非
sales
可以包含大量if值)。正如你提到的,它也更具可读性

您可以将
this
传递给
reduce
作为种子,并一起进行所有更改,但由于代码正在改变实例,因此使用更具功能性的方法无法获得多少好处


我会坚持使用forEach。

Richard的答案很好,但是如果你想坚持使用
reduce
来避免尽管是局部的变异,你可以这样做,同时仍然只访问每个对象一次。事实上,
reduce
的美妙之处在于,我们可以将数组转换为我们想要的任意值,所以让我们从中获得乐趣

export function tallySales(sales: Sale[]) {
  return sales.reduce((ac, {total, tax, discount, qty}) => ({
    total: ac.total + total,
    tax: ac.tax + tax, 
    discount: ac.discount + discount,      
    qty: ac.qty + qty
  }), {total: 0, tax: 0, discount: 0, qty: 0});
关于模块化的具体问题,使用上述风格绝不是更模块化,但它确实鼓励我们编写更多的可测试代码,因为我们用函数的输入和输出来表达东西。上面的函数可以很容易地进行测试,而改变类实例动态绑定的命令式版本测试起来更为复杂,尽管在本例中不一定要测试很多

有趣的是,它根本不是关于使用
reduce
而不是
forEach
。事实上,上面的函数可以用
forEach
编写,它将像
reduce
一样具有可维护性、可测试性和模块化。它更多地关系到如何使用
reduce
让我们进入用值来表达接口的思维框架,而不是修改与许多生产者和消费者相关的状态,从而隐式地推进程序