0

我有一个对象,其中我正在存储购物车的选择。因为这是一个 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 模式来缓存结果。
  • 另一个人认为我不应该在不传递匹配的函数输出的情况下使用 reduce map
  • 还有一些人同意,虽然 reduce 是正确的使用方法,但我应该改用foldl别名,因为它对未来的开发人员来说更清楚其意图是什么。

诚然,我对 FP 知之甚少,因此我reduce在 Underscore 中使用该方法纯粹是为了得出小计,而无需将其作为单独的属性存储在 JSON 服务器端。

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

4

1 回答 1

2

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

  • 这里基本上存在三个问题:实际代码效率、代码易读性和代码风格。最后一个与 IMO 无关,除非它影响代码库的易读性和一致性。

  • 在效率方面,_.reduce_.map+更有效_.reduce,所以你可以放弃这个想法。使用_.map创建一个具有转换后的值的新数组 - 没有必要这样做。

  • + 求和函数方法的_.each效率可能略低(您需要在其他地方跟踪您的运行总变量),并且在我看来它不太易读,因为它需要相关代码并将其从您所在的循环移得更远使用它。您也不会为您的操作获得一个干净的返回值 - 相反,您有一个变量挂在外部范围的某个地方,您需要首先创建然后重新使用它。

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

  • 在易读性方面,我强烈倾向于使用隐藏真正 JS 1.8 方法名称的下划线别名(对我来说,例外是.anyvs. .some,因为我发现它更易读)。在这种情况下,这意味着.reduce,不是.inject.foldl。这使JS开发人员更容易理解其意图,而 JS 开发人员就是您关心的人。

于 2013-08-20T23:22:40.630 回答