使用减少
:
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
block 开始,但随着时间的推移,它的大小逐渐增大,并且在某种程度上难以重构,因为它们彼此“捆绑”在一起。
您能分享一下您的经验吗?
最佳答案
理查德的答案很好,但如果你想坚持使用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});
关于模块化的具体问题,使用上述风格绝不是更模块化,但它确实鼓励我们编写更多可测试的代码,因为我们用函数的输入和输出来表达事物。上面的函数可以非常容易地测试,而改变类实例的动态绑定(bind)的命令式版本测试起来更加复杂,尽管在这种情况下不一定复杂。
有趣的是,这根本不是使用 reduce
与 forEach
的问题。事实上,上面的函数可以用 forEach
编写,并且它与使用 reduce
一样可维护、可测试且模块化。它更多地与使用reduce
如何让我们进入用值表达我们的接口(interface)的思维框架有关,而不是修改与许多生产者和消费者相关的状态以隐式地插入程序前进。
关于javascript - 几个小的reduce vs 一个大的forEach?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46873746/