从调用forEach()数组方法的方法返回。 JavaScript的

时间:2017-02-19 16:07:26

标签: javascript arrays foreach ecmascript-5

我正在使用从JavaScript中的数组调用的forEach()方法。当我在为数组中的每个元素调用的方法内部的某处写return;时,我会从为特定元素调用的方法返回,这就是全部。但我真正想要的是从名为forEach()的数组的方法中返回。这是代码:

    function addToCart(pizza, size)
    {
        Cart.forEach(function(cartItem)
        {
            if(pizzaAndSizeAreTheSame(cartItem, pizza, size))
            {
                cartItem.quantity++;
                updateCart();
                //Want go out from addToCart if this return is reached
                return;
            }
        });

        //Don`t want the code run after return;
        Cart.push
        ({
            pizza: pizza,
            size: size,
            quantity: 1
        });
        updateCart();
    }

这是我到目前为止所提出的解决方案:

    function addToCart(pizza, size)
{
    var leaveTheMethod = false;
    Cart.forEach(function(cartItem)
    {
        if(pizzaAndSizeAreTheSame(cartItem, pizza, size))
        {
            cartItem.quantity++;
            updateCart();
            leveTheMethod = true;
        }
    });
    if(leaveTheMethod)
        {return;}

    //Don`t want the code run after return;
    Cart.push
    ({
        pizza: pizza,
        size: size,
        quantity: 1
    });
    updateCart();
}

我想知道是否有更好的解决方案。

与该问题相比:How to short circuit Array.forEach like calling break? 我对于知道forEach()循环中的新方法并不感兴趣,我想要从forEach()中解脱,而不是包含forEach()调用方法。

4 个答案:

答案 0 :(得分:1)

function addToCart(pizza, size) {
    var res = Cart.some(function(cartItem)) {
        if(pizzaAndSizeAreTheSame(cartItem, pizza, size)) {
            cartItem.quantity++;
            updateCart();
            //Want go out from addToCart if this return is reached
            return true;
        }
        return false;
    });

    if(res) {
      return;
    }
    //Don`t want the code run after return;
    Cart.push({
        pizza: pizza,
        size: size,
        quantity: 1
    });
    updateCart();
}

答案 1 :(得分:1)

引用Mozilla Developer Network

  

除了抛出异常之外,没有办法停止或中断forEach()循环。如果你需要这样的行为,forEach()方法是错误的工具,而是使用普通循环。如果要测试谓词的数组元素并需要布尔返回值,则可以使用every()或some()。如果可用,新方法find()或findIndex()也可用于在真正的谓词上提前终止。

话虽如此,我相信你的解决方案是设置一个标志来退出函数是最合适和最简单的。

答案 2 :(得分:0)

您可以使用Array#find执行以下操作:

function addToCart(pizza, size)
{
    // find the first item where the condition is true, 
    // or undefined if there is none
    var sameSizeItem = Cart.find(function (item) {
        return pizzaAndSizeAreTheSame(item, pizza, size);
    });

    if (sameSizeItem) {
        sameSizeItem.quantity++;
        updateCart();
        return;
    }

    Cart.push({
        pizza: pizza,
        size: size,
        quantity: 1
    });

    updateCart();
}

稍微调整一下,你可以避免在两个不同的地方updateCart()

function addToCart(pizza, size)
{
    // find the first item where the condition is true, 
    // or undefined if there is none
    var sameSizeItem = Cart.find(function (item) {
        return pizzaAndSizeAreTheSame(item, pizza, size);
    });

    if (sameSizeItem) {
        sameSizeItem.quantity++;
    } else {
        Cart.push({
            pizza: pizza,
            size: size,
            quantity: 1
        });
    }

    updateCart();
}

如果您定位的环境并非全部支持Array#find,则可以获得polyfill from MDN

答案 3 :(得分:0)

您可以通过使购物车成为具有添加方法和quantities属性的对象来改进。该属性将具有比萨饼和大小的不同组合的关键,并且作为它们的数量的值。这将取代您目前拥有的阵列。

然后,您可以直接访问这些属性,而无需进行循环,也无需使用函数pizzaAndSizeAreTheSame

以下是您可以实现的示例:



function Cart() { // Put all cart functionality in one object/constructor
    // Make the list of items in the cart an object instead of an array
    this.quantities = {}; 
}

// Define the methods on the Cart prototype
Cart.prototype = {
    update: function() {
        // whatever logic you had in updateCart
    },
    add: function(pizza, size) {
        var key = pizza + '|' + size;
        this.quantities[key] = (this.quantities[key] || 0) + 1;
        this.update();
    },
    toArray: function() { // In case you need your original format also
        return Object.keys(this.quantities).map(function (key) {
            return {
                quantity: this[key],
                pizza: key.split('|')[0],
                size: key.split('|')[1]
            };
        }.bind(this.quantities))
    }
};

// Demo: create a cart and add items to it.
cart = new Cart();
cart.add('Four seasons', 'medium');
cart.add('Four seasons', 'medium');
cart.add('Vegetarian', 'large');
console.log(cart.toArray());

.as-console-wrapper { max-height: 100% !important; top: 0; }