[1,2,3].forEach(function(el) {
if(el === 1) break;
});
JavaScriptの新しいforEach
メソッドを使ってこれを行うにはどうすればよいですか?私はreturn;
、return false;
およびbreak
を試しました。 break
はクラッシュし、return
は何もしないで繰り返しを続けます。
break
にforEach
への組み込み機能はありません。実行を中断するには、なんらかの例外をスローする必要があります。例えば。
var BreakException = {};
try {
[1, 2, 3].forEach(function(el) {
console.log(el);
if (el === 2) throw BreakException;
});
} catch (e) {
if (e !== BreakException) throw e;
}
JavaScriptの例外はそれほど美しくありません。あなたが本当にその内部にfor
を必要とするならば、伝統的なbreak
ループがより適切かもしれません。
Array#some
を使用代わりに Array#some
を使用してください。
[1, 2, 3].some(function(el) {
console.log(el);
return el === 2;
});
これは、配列順に実行されたいずれかのコールバックがsome
を返し、残りの実行を短絡するとすぐにtrue
がtrue
を返すためです。
some
、その逆の every
(return false
で停止します)、およびforEach
はすべてECMAScript Fifth Editionのメソッドで、欠落しているブラウザのArray.prototype
に追加する必要があります。
新しい for of loop を使用してECMAScript2015(別名ES6)でこれを実行するさらに良い方法があります。たとえば、次のコードでは5の後に配列要素は表示されません。
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (let el of arr) {
console.log(el);
if (el === 5) {
break;
}
}
ドキュメントから:
for ... in と for ... of の両方のステートメントが、何かを繰り返します。それらの間の主な違いはそれらが反復するものにあります。 for ... in ステートメントは、オブジェクトの列挙可能なプロパティを元の挿入順で繰り返します。 for ... of ステートメントは、反復可能オブジェクトが反復対象として定義しているデータを反復します。
繰り返しにインデックスが必要ですか。 Array.entries()
を使用できます。
for (const [index, el] of arr.entries()) {
if ( index === 5 ) break;
}
every methodを使用できます。
[1,2,3].every(function(el) {
return !(el === 1);
});
ES6
[1,2,3].every( el => el !== 1 )
古いブラウザのサポート用
if (!Array.prototype.every)
{
Array.prototype.every = function(fun /*, thisp*/)
{
var len = this.length;
if (typeof fun != "function")
throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in this &&
!fun.call(thisp, this[i], i, this))
return false;
}
return true;
};
}
より詳細 ここ 。
MDNのArray.prototype.forEach()
のドキュメントからの引用)
停止または中断する方法はありません
forEach()
ループには、例外をスローする以外の方法があります。このような振る舞いが必要な場合は、.forEach()
メソッドは間違ったツールです。代わりに単純なループを使用してください。述語について配列要素をテストしていてブール値の戻り値が必要な場合は、代わりにevery()
またはsome()
)を使用できます。
@bobinceが示唆しているように、(疑問のある)あなたのコードには、代わりに Array.prototype.some()
)を使ってください。
Array.prototype.some()
は、コールバックが真の値(Boolean
に変換されると真になる値)を返すものが見つかるまで、配列内に存在する各要素に対して1回コールバック関数を実行します。そのような要素が見つかると、some()
は直ちにtrueを返します。それ以外の場合、some()
はfalseを返します。コールバックは、値が割り当てられている配列のインデックスに対してのみ呼び出されます。削除されたインデックスや値が割り当てられたことのないインデックスに対しては呼び出されません。
残念ながら、この場合はforEach
を使わない方がずっと良いでしょう。代わりに通常のfor
ループを使用してください。そうすれば、期待通りに動作するようになります。
var array = [1, 2, 3];
for (var i = 0; i < array.length; i++) {
if (array[i] === 1){
break;
}
}
コールバック関数内でfalseを返すことができるので、jquery
のeach
メソッドを使用することを検討してください。
$.each(function(e, i) {
if (i % 2) return false;
console.log(e)
})
Lodashライブラリはmap/reduce/foldなどと連鎖できる takeWhile
メソッドも提供します。
var users = [
{ 'user': 'barney', 'active': false },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': true }
];
_.takeWhile(users, function(o) { return !o.active; });
// => objects for ['barney', 'fred']
// The `_.matches` iteratee shorthand.
_.takeWhile(users, { 'user': 'barney', 'active': false });
// => objects for ['barney']
// The `_.matchesProperty` iteratee shorthand.
_.takeWhile(users, ['active', false]);
// => objects for ['barney', 'fred']
// The `_.property` iteratee shorthand.
_.takeWhile(users, 'active');
// => []
あなたのコード例から、Array.prototype.find
があなたが探しているものであるように見えます: Array.prototype.find() そして Array.prototype.findIndex()
[1, 2, 3].find(function(el) {
return el === 2;
}); // returns 2
Dean Edwardの提案 を使用してエラーをキャッチせずにループから抜け出すためにStopIterationエラーをスローする場合は、次の関数を使用できます( 元々ここから )。
// Use a closure to prevent the global namespace from be polluted.
(function() {
// Define StopIteration as part of the global scope if it
// isn't already defined.
if(typeof StopIteration == "undefined") {
StopIteration = new Error("StopIteration");
}
// The original version of Array.prototype.forEach.
var oldForEach = Array.prototype.forEach;
// If forEach actually exists, define forEach so you can
// break out of it by throwing StopIteration. Allow
// other errors will be thrown as normal.
if(oldForEach) {
Array.prototype.forEach = function() {
try {
oldForEach.apply(this, [].slice.call(arguments, 0));
}
catch(e) {
if(e !== StopIteration) {
throw e;
}
}
};
}
})();
上記のコードにより、独自のtry-catch句を使用しなくても、次のようなコードを実行することができます。
// Show the contents until you get to "2".
[0,1,2,3,4].forEach(function(val) {
if(val == 2)
throw StopIteration;
alert(val);
});
覚えておくべき重要なことの1つは、Array.prototype.forEach関数が既に存在する場合にのみ更新されることです。まだ存在しない場合は、変更されません。
簡単な答え:これにはfor...break
を使用するか、forEach
を壊さないようにコードを変更してください。 for...break
をエミュレートするために.some()
または.every()
を使用しないでください。 for...break
ループを回避するようにコードを書き直すか、for...break
を使用してください。 for...break
の代わりにこれらの方法を使うたびに、神は子猫を殺します。
長い答え:
.some()
と.every()
は両方ともboolean
値を返し、.some()
は渡された関数がtrue
を返す場合はtrue
を返し、渡された関数がfalse
を返す場合はeveryはfalse
を返します。これがその機能の意味です。意味のないことに関数を使用することは、CSSの代わりにレイアウトのためにテーブルを使用するよりもはるかに悪いです。なぜなら、それはあなたのコードを読む誰もがいらいらするからです。
また、これらのメソッドをfor...break
の代替として使用する唯一の方法は、副作用を発生させること(.some()
callback関数の外側でいくつかの変数を変更すること)であり、これはfor...break
と大差ありません。
したがって、.some()
または.every()
をfor...break
ループの代替として使用しても、副作用がないわけではありません。これは、for...break
よりもそれほど明確ではないため、これは苛立たしい方法です。
for...break
に必要がないように、いつでもコードを書き直すことができます。 .filter()
を使用して配列をフィルター処理したり、.slice()
を使用して配列を分割したりすることができます。その後、配列のその部分に.forEach()
または.map()
を使用します。
別のサイトでこの解決策を見つけました。 forEachをtry/catchシナリオでラップすることができます。
if(typeof StopIteration == "undefined") {
StopIteration = new Error("StopIteration");
}
try {
[1,2,3].forEach(function(el){
alert(el);
if(el === 1) throw StopIteration;
});
} catch(error) { if(error != StopIteration) throw error; }
これは私が問題を解決するために思いついたものです。
Array.prototype.each = function(callback){
if(!callback) return false;
for(var i=0; i<this.length; i++){
if(callback(this[i], i) == false) break;
}
};
そして、それを使ってそれを呼ぶでしょう:
var myarray = [1,2,3];
myarray.each(function(item, index){
// do something with the item
// if(item != somecondition) return false;
});
コールバック関数内でfalseを返すと、ブレークが発生します。それが実際にうまくいかないかどうか私に知らせてください。
反復後に配列にアクセスする必要がない場合は、配列の長さを0に設定することで回避できます。反復後も配列の長さを必要とする場合は、スライスを使用してクローンを作成できます。
[1,3,4,5,6,7,8,244,3,5,2].forEach(function (item, index, arr) {
if (index === 3) arr.length = 0;
});
またはクローンを使って:
var x = [1,3,4,5,6,7,8,244,3,5,2];
x.slice().forEach(function (item, index, arr) {
if (index === 3) arr.length = 0;
});
これは、コードにランダムなエラーを投げるよりはるかに優れた解決策です。
これはforループですが、forEach()のようにループ内でオブジェクト参照を維持しますが、実行することもできます。
var arr = [1,2,3];
for (var i = 0, el; el = arr[i]; i++) {
if(el === 1) break;
}
私が思い付いたもう一つの概念:
function forEach(array, cb) {
var shouldBreak;
function _break() { shouldBreak = true; }
for (var i = 0, bound = array.length; i < bound; ++i) {
if (shouldBreak) { break; }
cb(array[i], i, array, _break);
}
}
// Usage
forEach(['a','b','c','d','e','f'], function (char, i, array, _break) {
console.log(i, char);
if (i === 2) { _break(); }
});
forEach
構文を使い続けたい場合は、これを効率的にする方法です(ただし、通常のforループほどは良くありません)。ループから抜け出したいかどうかを知っている変数があるかどうかすぐに調べてください。
この例では、 done 情報を格納する必要があるforEach
の周囲に function scope を作成するために無名関数を使用しています。
(function(){
var element = document.getElementById('printed-result');
var done = false;
[1,2,3,4].forEach(function(item){
if(done){ return; }
var text = document.createTextNode(item);
element.appendChild(text);
if (item === 2){
done = true;
return;
}
});
})();
<div id="printed-result"></div>
私の二セント。
さらに別のアプローチ
var wageType = types.filter(function(element){
if(e.params.data.text == element.name){
return element;
}
});
console.dir(wageType);
私はそれが正しい方法ではないことを知っています。それはループを壊すことではありません。それはJugadです
let result = true;
[1, 2, 3].forEach(function(el) {
if(result){
console.log(el);
if (el === 2){
result = false;
}
}
});
そのために nullhack を使用します。これはnull
のプロパティにアクセスしようとしますが、これはエラーです。
try {
[1,2,3,4,5]
.forEach(
function ( val, idx, arr ) {
if ( val == 3 ) null.NULLBREAK;
}
);
} catch (e) {
// e <=> TypeError: null has no properties
}
//
前述のように、.forEach()
を壊すことはできません。
ES6イテレータを使ったforeachのもう少し現代的な方法は次のとおりです。反復時にindex
/value
に直接アクセスできるようにします。
const array = ['one', 'two', 'three'];
for (const [index, val] of array.entries()) {
console.log('item:', { index, val });
if (index === 1) {
console.log('break!');
break;
}
}
出力:
item: { index: 0, val: 'one' }
item: { index: 1, val: 'two' }
break!
あなたは私のために働く以下のコードに従うことができます。
var loopStop = false;
YOUR_ARRAY.forEach(function loop(){
if(loopStop){ return; }
if(condition){ loopStop = true; }
});
array.prototype.every
関数を使用します。これは、ループを解消するためのユーティリティを提供します。こちらの例を参照してください Mozilla開発者ネットワーク上のJavascriptドキュメント
私はfor in
を使うのが好きです
var words = ['a', 'b', 'c'];
var text = '';
for (x in words) {
if (words[x] == 'b') continue;
text += words[x];
}
console.log(text);
for in
はforEach
とよく似た働きをします。内部にreturn to exit関数を追加することができます。パフォーマンスも向上しました。
あなたはまだすべての要素を循環させるので、これは最も効率的ではありません、しかし私はそれが非常に単純なものを考える価値があるかもしれないと思いました:
let keepGoing = true;
things.forEach( (thing) => {
if (noMore) keepGoing = false;
if (keepGoing) {
// do things with thing
}
});
"find"で試してください。
var myCategories = [
{category: "start", name: "Start", color: "#AC193D"},
{category: "action", name: "Action", color: "#8C0095"},
{category: "exit", name: "Exit", color: "#008A00"}
];
function findCategory(category) {
return myCategories.find(function(element) {
return element.category === category;
});
}
console.log(findCategory("start"));
// output: { category: "start", name: "Start", color: "#AC193D" }
支持を得て、@ bobinceに同意します。
また、FYI:
Prototype.jsには、この目的のためのものがあります。
<script type="text/javascript">
$$('a').each(function(el, idx) {
if ( /* break condition */ ) throw $break;
// do something
});
</script>
$break
は、Prototype.jsによって内部的にキャッチされ処理され、 "each"サイクルを中断しますが、外部エラーを生成しません。
詳細については Prototype.JS API を参照してください。
jQueryにも方法があります。ループを早期に中断するには、ハンドラにfalseを返すだけです。
<script type="text/javascript">
jQuery('a').each( function(idx) {
if ( /* break condition */ ) return false;
// do something
});
</script>
詳細については jQuery API を参照してください。
あなたのケースのようにすでにあなたの配列にある要素の値に基づいてブレークする必要があるならば(すなわち、ブレーク条件が配列にその要素値が割り当てられた後に変わるランタイム変数に依存しないなら)以下のように slice() と indexOf() の関係.
ForEachが 'Apple'に到達したときに中断する必要がある場合は、次のものを使用できます。
var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var fruitsToLoop = fruits.slice(0, fruits.indexOf("Apple"));
// fruitsToLoop = Banana,Orange,Lemon
fruitsToLoop.forEach(function(el) {
// no need to break
});
述べたように W3Schools.comで / slice()メソッドは、新しい配列オブジェクトとして、配列内の選択された要素を返します。元の配列は変更されません。
JSFiddle でそれを参照してください。
誰かに役立つことを願っています。