0

我有一些我在紧要关头写的 JavaScript,但我认为它可以被比我聪明的人大大优化。这段代码在相对较小的对象上运行,但它运行了相当多的次数,所以它值得做对:

/**
 *  Determine the maximum quantity we can show (ever) for these size/color combos
 *
 *  @return int=settings.limitedStockThreshold
 */
function getMaxDefaultQuantity() {
    var max_default_quantity = 1;

    if (inventory && inventory.sizes) {
        sizecolor_combo_loop:
        for (var key in inventory.sizes) {
            if (inventory.sizes[key].combos) {
                for (var key2 in inventory.sizes[key].combos) {
                    var sizecolor_combo = inventory.sizes[key].combos[key2];
                    if (isBackorderable(sizecolor_combo)) {
                    //if even one is backorderable, we can break out
                        max_default_quantity = settings.limitedStockThreshold;
                        break sizecolor_combo_loop;
                    } else {
                    //not backorderable, get largest quantity (sizecolor_combo or max_default_quantity)
                        var qoh = parseInt(sizecolor_combo.quantityOnHand || 1);
                        if (qoh > max_default_quantity) {
                            max_default_quantity = qoh;
                        };
                    };
                };
            };
        };
    };

    return Math.min(max_default_quantity, settings.limitedStockThreshold);
};

首先,库存是通过 JSON 返回的对象。它有一个属性inventory.sizes,其中包含产品的所有可用尺寸。每个尺码都有一个属性inventory.sizes.combos,它映射到一个尺码的所有可用颜色。每个组合还有一个属性quantityOnHand,它告诉特定组合可用的数量。(返回的JSON结构不能修改)

代码所做的是遍历每个尺寸,然后是每个尺寸的组合。然后它检查尺寸-颜色组合是否可延期交货(通过另一种方法)。如果任何组合可延期交货,我们可以停止,因为默认数量已在别处定义。如果组合不可延期交货,则 max_default_quantity 是我们找到的最大数量(最大为 settings.limitedStockThreshold)。

我真的不喜欢嵌套的 for 循环,而且我对数学和默认值的处理感觉过于复杂。

此外,如果这有助于清理它,那么整个函数将被包装在一个更大的 jQuery 对象中。

4

2 回答 2

0

您是否考虑过使用 map-reduce?查看函数式方法的实时示例。

这个特定的示例使用underscore.js,因此我们可以将其保持在优雅的水平,而无需实现细节。

function doStuff(inventory) {
    var max = settings.limitedStockThreshold;
    if (!(inventory && inventory.sizes)) return;

    var quantity = _(inventory.sizes).chain()
        .filter(function(value) {
            return value.combos;
        })
        .map(function(value) {
            return _(value.combos).chain()
                .map(function(value) {
                    return isBackorderable(value) ? max : value.quantityOnHand;
                })
                .max().value();
        })
        .max().value();

    return Math.min(quantity, max);
}

至于解释:

我们采用inventory.sizes 设置并删除任何不包含组合的内容。然后我们将每个尺寸映射到其颜色的最大数量。我们将每个组合映射到它的数量或最大数量(如果可退还)。然后我们取该集合的最大值。

最后,我们采用每个尺寸的最大一组 maxQuantities。

我们仍然有效地进行了双重 for 循环,因为我们在片场拿了两个.max,但它看起来不那么脏。

还有一些你已经到位的 if 检查仍然存在。

[编辑]

我很确定上面的代码可以进一步优化。但这是一种不同的看待它的方式。

于 2011-01-26T00:35:47.917 回答
0

不幸的是,如果您必须支持较旧的浏览器,JavaScript 并没有太多优雅的集合处理功能,因此在没有其他库的帮助的情况下,您编写的嵌套循环是可行的方法。您可以考虑将这些值预先计算在服务器端,也许是缓存,并将其包含在 JSON 中以避免一次又一次地运行相同的计算。

于 2011-01-26T00:15:49.357 回答