下划线因增加价格而减少

时间:2013-08-19 19:16:38

标签: javascript underscore.js reduce

我有一个对象,其中我存储购物车的选择。因为这是一个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。
  • 还有人认为虽然reduce是正确的使用方法,但我应该使用foldl别名,因为它对未来的开发者更清楚意图是什么。

不可否认,我对FP知之甚少,所以我在Underscore中使用reduce方法纯粹是一种结束导出小计的方法,而不必将其存储为JSON服务器端的单独属性

请向我解释为什么reduce是或者不是“正确”方法来生成对象属性的总和。显然,我不是在寻找一种纯函数方法,因为我只使用reduce作为实用程序。

1 个答案:

答案 0 :(得分:2)

这是一个非常主观的问题,所以我想我会给出一个主观的答案:

  • 这里基本上有三件事:实际的代码效率,代码易读性和代码风格。最后一个对IMO并不重要,只要它影响可读性和代码库的一致性。

  • 就效率而言,_.reduce_.map + _.reduce效率更高,因此您可以放弃这个想法。使用_.map创建一个包含转换值的新数组 - 不需要这样做。

  • _.each +求和函数方法可能效率稍低(你需要在其他地方跟踪你的running-total变量)而且我认为它不太清晰,因为它需要相关的代码并将它从您正在使用它的循环中进一步移动。你也没有为你的操作获得一个漂亮的干净返回值 - 相反,你有一个变量挂在外部范围的某个地方,你需要先创建然后重新使用。

  • 我认为“memoization”在这里没有多大意义。您可能希望缓存给定购物车的返回值,并在项目更改时使其无效,但这实际上并不是记忆。当a)易于散列的输入总是产生相同的答案,并且b)计算答案是昂贵的时,记忆是有意义的。在这种情况下,计算总和可能比对输入(您的项目列表)进行哈希处理要便宜。

  • 就易读性而言,我强烈倾向于使用影响真正JS 1.8方法名称的Underscore别名(对我而言,例外是.any.some,因为我发现它更清晰易读)。在这种情况下,这意味着.reduce,而不是.inject.foldl。这使得 JS 开发人员更容易理解其目的,而JS开发人员是您关心的人。