2017-02-19 11 views
0

JavaScriptの配列から呼び出されたforEach()メソッドを使用しています。配列のすべての要素のために呼び出されるメソッドのどこかにreturn;を書き込むと、特定の要素のために呼び出されたメソッドから戻ります。しかし、私が実際に望むのは、forEach()という配列のメソッドから戻ることです。ここでは、コードは次のとおりです。forEach()配列メソッドが呼び出されたメソッドからの戻り値。 JavaScript

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

を私が問題に任意のより良い解決策がある知っているしたいと思います:

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

ここで私はこれまでのところまで来たとソリューションです。その質問に比べ

How to short circuit Array.forEach like calling break? 私はforEachの()ループ内で新しい方法を知ることに興味がないと私はないのforEach(から壊したく)が、forEachの()の呼び出し元のメソッドを網羅するから。

+1

は何かが発見されたかどうかを確認するために比較 'pizzaAndSizeAreTheSame'です:?ここ

はそれを実装することができますの例ですか。その場合は、['find'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)または[' some'](https:// developer .mozilla.org/ja-jp/docs/Web/JavaScript/Reference/Global_Objects/Array/some)! –

+0

文から返る唯一の方法はスロー/キャッチすることです: http://stackoverflow.com/questions/2641347/how-to-short-circuit-array-foreach-like-calling-break – laser

+0

右、 '.some ()はあなたが探しているものです。コールバックが 'true'を返すと、反復は止まり、' .some() 'も' true'を返します。 – Pointy

答えて

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

addToCart()から戻ってきますか? –

+0

はい、最初に 'some'を返し、' if(res) 'で' addToCart'を返します。 +1 – trincot

+0

@trincot、それは私の解決策と変わらない。 –

1

Mozilla Developer Networkを引用すると:停止または例外をスローする以外のforEach()ループを打破する方法はありません

。このような振る舞いが必要な場合は、forEach()メソッドが間違ったツールになります。代わりにプレーンループを使用します。述部の配列要素をテストしていて、ブール戻り値が必要な場合は、every()またはsome()を代わりに使用できます。可能であれば、新しいメソッドfind()またはfindIndex()を使用して、真の述語について早期終了することもできます。

私はあなたの解決策は、関数から復帰するフラグを設定していると信じている最も適切で簡単です。

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

もう少し調整をして、2つの異なる場所でupdateCart()を避けることができます:あなたはArray#findで、次のことを行うことができ

0

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を取得できます。

0

@squGEIm's answerあなたは.forEach()から短絡できないことを示す素晴らしい仕事をしていますが、私はあなたがフラグと共にそれを使用し続けるべきであるという意見はありません。

forEachコールバック関数で更新するのではなく、要素が存在する場合は最初にその要素を見つけてカートを更新するようにメソッドを変更する必要があると思います。その方法では、ループ内のメソッドからreturnする必要はありません。それはすべてのブラウザでサポートされていない以外

Array.prototype.find()方法は、仕事のために完璧になる:

function addToCart(pizza, size) { 
    var pizzaCartItem = Cart.find(function(cartItem) { 
     return pizzaAndSizeAreTheSame(cartItem, pizza, size); 
    }); 

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

あなたはfindメソッドの独自のバージョンを書きたいことがあります。

function findArrayElement(arr, callback) { 
    for (var i = 0, len = arr.length; i < len; i++) { 
     if (callback.call(null, arr[i], i, arr)) { 
      return arr[i]; 
     } 
    } 
} 

function addToCart(pizza, size) { 
    var pizzaCartItem = findArrayElement(Cart, function(cartItem) { 
     return pizzaAndSizeAreTheSame(cartItem, pizza, size); 
    }); 

    if (pizzaCartItem) { 
     pizzaCartTime.quantity++; 
    } else { 
     Cart.push({ pizza: pizza, size: size, quantity: 1 }); 
    } 
    updateCart(); 
} 
+0

forEachをfindに変更するのを忘れてしまいました。あなたの例はあなたの手前に5分前に投稿したものと同じです。 – JLRishe

+0

@JLRishe - タイプミスを指摘してくれてありがとう。 –

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

関連する問題