Return 来自调用 forEach() 数组方法的方法。 JavaScript

Return from a method in which forEach() array method was called. JavaScript

我正在使用从 JavaScript 中的数组调用的 forEach() 方法。当我在为数组中的每个元素调用的方法中的某处写 return; 时,我从为特定元素调用的方法中写出 return ,仅此而已。但我真正想要的是从数组调用forEach() 的方法中return 出来。这是代码:

    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() 调用方方法。

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();
}

引用Mozilla Developer Network:

There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool, use a plain loop instead. If you are testing the array elements for a predicate and need a Boolean return value, you can use every() or some() instead. If available, the new methods find() or findIndex() can be used for early termination upon true predicates as well.

话虽如此,我相信您在函数外设置标志 return 的解决方案是最合适和简单的。

您可以使用 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

您可以通过使您的购物车成为一个具有添加方法和 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; }