我有一个对象,其中我存储购物车的选择。因为这是一个Backbone应用程序,我决定导出购物车项目的小计,我会使用reduce
按数量添加商品价格:
这是一个(人为的)例子:
var App = {
cart : {
item : []
}
}
//...
App.cart.item.push({ qty: 1, price: 34.95});
App.cart.item.push({ qty: 3, price: 24.95});
App.cart.item.push({ qty: 4, price: 1.99});
App.cart.item.push({ qty: 13, price: .99});
渲染视图时,小计的计算方法如下:
_.reduce(App.cart.item,function(memo, num){ return memo + (num.price * num.qty); },0)
引发了一些争论:
reduce
不是在这里使用的正确方法,而是使用each
并传递给求和函数,并可能使用memoize模式来缓存结果。< / LI>
map
的函数输出的情况下使用reduce。foldl
别名,因为它对未来的开发者更清楚意图是什么。不可否认,我对FP知之甚少,所以我在Underscore中使用reduce
方法纯粹是一种结束导出小计的方法,而不必将其存储为JSON服务器端的单独属性
请向我解释为什么reduce
是或者不是“正确”方法来生成对象属性的总和。显然,我不是在寻找一种纯函数方法,因为我只使用reduce
作为实用程序。
答案 0 :(得分:2)
这是一个非常主观的问题,所以我想我会给出一个主观的答案:
这里基本上有三件事:实际的代码效率,代码易读性和代码风格。最后一个对IMO并不重要,只要它影响可读性和代码库的一致性。
就效率而言,_.reduce
比_.map
+ _.reduce
效率更高,因此您可以放弃这个想法。使用_.map
创建一个包含转换值的新数组 - 不需要这样做。
_.each
+求和函数方法可能效率稍低(你需要在其他地方跟踪你的running-total变量)而且我认为它不太清晰,因为它需要相关的代码并将它从您正在使用它的循环中进一步移动。你也没有为你的操作获得一个漂亮的干净返回值 - 相反,你有一个变量挂在外部范围的某个地方,你需要先创建然后重新使用。
我认为“memoization”在这里没有多大意义。您可能希望缓存给定购物车的返回值,并在项目更改时使其无效,但这实际上并不是记忆。当a)易于散列的输入总是产生相同的答案,并且b)计算答案是昂贵的时,记忆是有意义的。在这种情况下,计算总和可能比对输入(您的项目列表)进行哈希处理要便宜。
就易读性而言,我强烈倾向于使用影响真正JS 1.8方法名称的Underscore别名(对我而言,例外是.any
与.some
,因为我发现它更清晰易读)。在这种情况下,这意味着.reduce
,而不是.inject
或.foldl
。这使得 JS 开发人员更容易理解其目的,而JS开发人员是您关心的人。