[1,2,3].forEach(function(el) { if(el === 1) break; });
JavaScript에서 forEach
메서드를 사용하여 이 작업을 수행하려면 어떻게 해야 합니까? return;
시도했다; , return false;
그리고 break
. break
가 충돌하고 return
은 반복을 계속하는 것 외에는 아무것도 하지 않습니다.
질문자 :Scott Klarenbach
[1,2,3].forEach(function(el) { if(el === 1) break; });
JavaScript에서 forEach
메서드를 사용하여 이 작업을 수행하려면 어떻게 해야 합니까? return;
시도했다; , return false;
그리고 break
. break
가 충돌하고 return
은 반복을 계속하는 것 외에는 아무것도 하지 않습니다.
forEach
break
하는 기본 제공 기능은 없습니다. 실행을 중단하려면 일종의 예외를 throw해야 합니다. 예를 들어
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 예외는 그다지 아름답지 않습니다. 내부 break
해야 하는 경우 전통적인 for
루프가 더 적절할 수 있습니다.
Array#some
사용 #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 루프를 사용하여 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 문은 iterable 객체가 반복하도록 정의한 데이터를 반복합니다.
반복에 인덱스가 필요하십니까? Array.entries()
사용할 수 있습니다.
for (const [index, el] of arr.entries()) { if ( index === 5 ) break; }
모든 방법을 사용할 수 있습니다.
[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; }; }
자세한 내용은 여기 .
Array.prototype.forEach()
의 MDN 문서 에서 인용:
예외를 throw하는 것 외에는
forEach()
루프를 중지하거나 중단 할 수 있는 방법이 없습니다. 이러한 동작이 필요한 경우.forEach()
메서드가 잘못된 도구 이므로 대신 일반 루프를 사용하세요. 술어에 대한 배열 요소를 테스트하고 부울 반환 값이 필요한 경우 대신every()
또는some()
@bobince가 제안한 대로 귀하의 코드(질문에서)의 경우 Array.prototype.some()
사용하십시오. 그것은 당신의 사용 사례에 아주 잘 맞습니다.
Array.prototype.some()
Boolean
변환할 때 true가 되는 값)을 반환하는 값을 찾을 때까지 배열에 있는 각 요소에 대해 콜백 함수를 한 번 실행합니다. 그러한 요소가 발견되면some()
즉시 true를 반환합니다. 그렇지 않으면some()
은 false를 반환합니다. 콜백은 값이 할당된 배열의 인덱스에 대해서만 호출됩니다. 삭제되었거나 값이 할당된 적이 없는 인덱스에 대해서는 호출되지 않습니다.
forEach
사용하지 않는 것이 훨씬 나을 것입니다. 대신 일반 for
루프를 사용하면 예상대로 정확하게 작동합니다.
var array = [1, 2, 3]; for (var i = 0; i < array.length; i++) { if (array[i] === 1){ break; } }
코드 예제에서 Array.prototype.find
가 찾고 있는 것처럼 보입니다: Array.prototype.find() 및 Array.prototype.findIndex()
[1, 2, 3].find(function(el) { return el === 2; }); // returns 2
콜백 함수 내에서 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'); // => []
Dean Edward의 제안 을 사용하고 StopIteration 오류를 발생시켜 오류를 포착하지 않고도 루프를 벗어나고 싶다면 다음 함수를 사용할 수 있습니다( 원래 here ):
// 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); });
기억해야 할 한 가지 중요한 점은 이것이 이미 존재하는 경우에만 Array.prototype.forEach 함수를 업데이트한다는 것입니다. 이미 존재하지 않는 경우 수정하지 않습니다.
짧은 대답: for...break
forEach
깨지지 않도록 코드를 변경하십시오. .some()
또는 .every()
를 사용 for...break
를 에뮬레이트하지 마십시오. for...break
루프를 피하기 위해 코드를 다시 작성 for...break
. 이 방법을 사용할 때마다 for...break
대안 신이 새끼 고양이를 죽입니다.
긴 대답:
.some()
와 .every()
을 모두 반환 boolean
값은 .some()
반환 true
에 대한 요소가 함수가 반환이 통과하면 true
모든 반환, false
에 대한 요소가 함수가 반환이 전달 된 경우 false
. 이것이 그 기능이 의미하는 바입니다. 의미가 없는 기능을 사용하는 것은 CSS 대신 레이아웃에 테이블을 사용하는 것보다 훨씬 나쁩니다. 왜냐하면 코드를 읽는 모든 사람을 짜증나게 하기 때문입니다.
for...break
대안으로 사용할 수 있는 유일한 방법은 부작용을 만드는 것입니다( .some()
for...break
와 크게 다르지 않습니다.
따라서 .some()
또는 .every()
를 for...break
루프 대안으로 사용하는 것은 부작용이 없습니다. 이것은 for...break
보다 훨씬 깨끗하지 않습니다. 이것은 실망스럽기 때문에 그렇지 않습니다. 더 나은.
for...break
가 필요하지 않도록 항상 코드를 다시 작성할 수 있습니다. 다음을 사용하여 배열을 필터링 할 수 있습니다 .filter()
, 사용 배열을 분할 할 수 있습니다 .slice()
등등, 다음 사용 .forEach()
또는 .map()
배열의 부분.
이것은 내가 문제를 해결하기 위해 생각해 낸 것입니다 ... 원래 질문자가 가지고 있던 문제를 해결한다고 확신합니다.
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를 반환하면 중단이 발생합니다. 실제로 작동하지 않는 경우 알려주십시오.
이전에 언급했듯이 .forEach()
중단할 수 없습니다.
다음은 ES6 Iterator로 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!
내가 생각해낸 또 다른 개념:
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(); } });
반복 후에 배열에 액세스할 필요가 없으면 배열의 길이를 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; });
코드에서 임의의 오류를 던지는 것이 훨씬 더 나은 솔루션입니다.
다른 사이트에서 이 솔루션을 찾았습니다. try/catch 시나리오에서 forEach를 래핑할 수 있습니다.
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; }
자세한 내용은 여기: http://dean.edwards.name/weblog/2006/07/enum/
이것은 for 루프이지만 forEach()와 마찬가지로 루프에서 객체 참조를 유지하지만 중단할 수 있습니다.
var arr = [1,2,3]; for (var i = 0, el; el = arr[i]; i++) { if(el === 1) break; }
또 다른 접근법
var wageType = types.filter(function(element){ if(e.params.data.text == element.name){ return element; } }); console.dir(wageType);
나는 그 목적을 위해 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
구문을 유지하려면 이것이 효율적으로 유지하는 방법입니다(일반 for 루프만큼 좋지는 않지만). 루프에서 벗어나고 싶은지 여부를 알고 있는 변수를 즉시 확인하십시오.
이 예제에서는 완료 정보를 저장하는 데 필요한 forEach
주변에 함수 범위 를 만들기 위해 익명 함수를 사용합니다.
(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>
내 2센트.
루프를 끊는 유틸리티를 제공 array.prototype.every
함수를 사용하십시오. Mozilla 개발자 네트워크에 대한 Javascript 문서의 예는 여기를 참조하십시오.
@bobince에 동의하고 찬성합니다.
또한 참고로:
Prototype.js에는 다음과 같은 목적이 있습니다.
<script type="text/javascript"> $$('a').each(function(el, idx) { if ( /* break condition */ ) throw $break; // do something }); </script>
$break
는 내부적으로 Prototype.js에 의해 포착 및 처리되어 "각각" 주기를 중단하지만 외부 오류는 생성하지 않습니다.
자세한 내용은 Prototype.JS API 를 참조하세요.
jQuery도 방법이 있습니다. 핸들러에서 false를 반환하여 루프를 조기에 중단하면 됩니다.
<script type="text/javascript"> jQuery('a').each( function(idx) { if ( /* break condition */ ) return false; // do something }); </script>
자세한 내용은 jQuery API 를 참조하세요.
이것은 여전히 모든 요소를 순환하기 때문에 가장 효율적이지는 않지만 매우 간단한 것을 고려할 가치가 있다고 생각했습니다.
let keepGoing = true; things.forEach( (thing) => { if (noMore) keepGoing = false; if (keepGoing) { // do things with thing } });
당신은 나를 위해 작동하는 아래의 코드를 따를 수 있습니다:
var loopStop = false; YOUR_ARRAY.forEach(function loop(){ if(loopStop){ return; } if(condition){ loopStop = true; } });
나는 그것이 옳지 않다는 것을 알고 있습니다. 루프를 깨는 것이 아닙니다. 쥬갓이다
let result = true; [1, 2, 3].forEach(function(el) { if(result){ console.log(el); if (el === 2){ result = false; } } });
귀하의 경우와 같이 이미 배열에 있는 요소의 값을 기반으로 중단해야 하는 경우(즉, 중단 조건이 배열에 요소 값이 할당된 후 변경될 수 있는 런타임 변수에 의존하지 않는 경우) 조합을 사용할 수도 있습니다 다음과 같이 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 에서 보기
누군가를 돕기를 바랍니다.
"찾기"로 시도:
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" }
Promise에서 함수를 래핑해 보지 않겠습니까?
내가 그것을 제기하는 유일한 이유는 forEach와 유사한 방식으로 작동하는 API의 함수를 사용하고 있기 때문입니다. 값을 찾으면 계속 반복되는 것을 원하지 않고 무언가를 반환해야 하므로 간단히 Promise를 해결하고 그렇게 할 것입니다.
traverseTree(doc): Promise<any> { return new Promise<any>((resolve, reject) => { this.gridOptions.api.forEachNode((node, index) => { //the above function is the one I want to short circuit. if(node.data.id === doc.id) { return resolve(node); } }); }); }
그런 다음 다음과 같은 결과로 작업을 수행하기만 하면 됩니다.
this.traverseTree(doc).then((result) => { this.doSomething(result); });
위의 예는 typescript에 있습니다. 단순히 유형을 무시하십시오. 논리는 루프에서 "탈출"하는 데 도움이 되기를 바랍니다.
현재 배열이 엉망이 되므로 구조 해제 기능을 사용하여 복사본을 만들어야 합니다...
예:
const arr = [1, 2, 3, 4, 5]; // Don't forget to work with a copy of the original array otherwise you will loose your data contained inside [...arr].forEach(function(value, index, copiedArrInstance) { if (index === 2) copiedArrInstance.length = 0; console.log(value); }); // you will still have your array intact console.log(arr);
break
, continue
, return
및 async
/ await
까지 허용 forEach
변형을 만들 수 있습니다. (TypeScript로 작성된 예제)
export type LoopControlOp = "break" | "continue" | ["return", any]; export type LoopFunc<T> = (value: T, index: number, array: T[])=>LoopControlOp; Array.prototype.ForEach = function ForEach<T>(this: T[], func: LoopFunc<T>) { for (let i = 0; i < this.length; i++) { const controlOp = func(this[i], i, this); if (controlOp == "break") break; if (controlOp == "continue") continue; if (controlOp instanceof Array) return controlOp[1]; } }; // this variant lets you use async/await in the loop-func, with the loop "awaiting" for each entry Array.prototype.ForEachAsync = async function ForEachAsync<T>(this: T[], func: LoopFunc<T>) { for (let i = 0; i < this.length; i++) { const controlOp = await func(this[i], i, this); if (controlOp == "break") break; if (controlOp == "continue") continue; if (controlOp instanceof Array) return controlOp[1]; } };
용법:
function GetCoffee() { const cancelReason = peopleOnStreet.ForEach((person, index)=> { if (index == 0) return "continue"; if (person.type == "friend") return "break"; if (person.type == "boss") return ["return", "nevermind"]; }); if (cancelReason) console.log("Coffee canceled because: " + cancelReason); }
const Book = {"Titles":[ {"Book3" : "BULLETIN 3"}, {"Book1" : "BULLETIN 1"}, {"Book2" : "BULLETIN 2"} ]} const findbystr = function(str) { Book.Titles.forEach(function(data) { if (typeof data[str] != 'undefined') { return data[str]; } }, str) } book = findbystr('Book1'); console.log(book);
출처 : http:www.stackoverflow.com/questions/2641347/short-circuit-array-foreach-like-calling-break
구성 오류: 이 구성 섹션은 이 경로에서 사용할 수 없습니다. (0) | 2021.12.21 |
---|---|
NullReferenceException이란 무엇이며 어떻게 수정합니까? (0) | 2021.12.21 |
Git 커밋에서 파일 제거 (0) | 2021.12.21 |
브라우저 창을 기준으로 HTML 요소의 위치(X,Y) 검색 (1) | 2021.12.21 |
호스트에서 Docker 컨테이너로 파일을 복사하는 방법은 무엇입니까? (0) | 2021.12.21 |