우리는 종종 행동을 반복해야 합니다.
예를 들어, 목록에서 상품을 하나씩 출력하거나 1부터 10까지의 각 숫자에 대해 동일한 코드를 실행하는 것입니다.
루프는 동일한 코드를 여러 번 반복하는 방법입니다.
for…of 및 for…in 루프
고급 독자를 위한 작은 공지입니다.
이 문서에서는 while , do..while 및 for(..;..;..) 기본 루프만 다룹니다.
다른 유형의 루프를 검색하여 이 문서를 방문했다면 다음 지침을 따르세요.
객체 속성을 반복하려면 for…in을 참조하세요.
배열과 반복 가능한 객체에 대한 반복은 for…of 및 반복 가능 항목을 참조하세요.
그렇지 않은 경우 계속 읽어보세요.
while 루프에는 다음과 같은 구문이 있습니다:
동안(조건) {
// 코드
// 소위 "루프 본문"
} condition 이 참이면 루프 본문의 code 실행됩니다.
예를 들어, 아래 루프는 i while i < 3 출력합니다.
내가 = 0이라고 하자;
while (i < 3) { // 0, 1, 2를 표시합니다.
경고(i);
나++;
}루프 본문의 단일 실행을 반복 이라고 합니다. 위 예제의 루프는 세 번 반복됩니다.
위의 예에서 i++ 누락된 경우 루프는 (이론적으로) 영원히 반복됩니다. 실제로 브라우저는 이러한 루프를 중지하는 방법을 제공하며 서버 측 JavaScript에서는 프로세스를 종료할 수 있습니다.
비교뿐만 아니라 모든 표현식이나 변수가 루프 조건이 될 수 있습니다. 조건은 while 에 의해 평가되고 부울로 변환됩니다.
예를 들어, while (i != 0) 작성하는 더 짧은 방법은 while (i) 입니다:
i = 3이라고 하자;
while (i) { // i가 0이 되면 조건이 거짓이 되고 루프가 멈춥니다.
경고(i);
나--;
}단일 행 본문에는 중괄호가 필요하지 않습니다.
루프 본문에 단일 문이 있는 경우 중괄호 {…} 를 생략할 수 있습니다.
i = 3이라고 하자; (i) 경고(i--);
조건 확인은 do..while 구문을 사용하여 루프 본문 아래로 이동할 수 있습니다.
하다 {
// 루프 본문
} while(조건);루프는 먼저 본문을 실행한 다음 조건을 확인하고 그것이 사실인 동안 계속해서 실행합니다.
예를 들어:
내가 = 0이라고 하자;
하다 {
경고(i);
나++;
} 동안(i < 3); 이 구문 형식은 조건이 참인지 여부에 관계없이 루프 본문을 한 번 이상 실행하려는 경우에만 사용해야 합니다. 일반적으로 다른 형식이 선호됩니다: while(…) {…} .
for 루프는 더 복잡하지만 가장 일반적으로 사용되는 루프이기도 합니다.
다음과 같습니다:
for(시작; 조건; 단계) {
// ... 루프 본문 ...
} 이 부분의 의미를 예를 통해 알아봅시다. 아래 루프는 i 대해 0 에서 3 까지(포함하지 않음)에 대해 alert(i) 실행합니다.
for (let i = 0; i < 3; i++) { // 0, 1, 2를 표시합니다.
경고(i);
} for 문을 부분별로 살펴보겠습니다.
| 부분 | ||
|---|---|---|
| 시작하다 | let i = 0 | 루프에 진입하면 한 번 실행됩니다. |
| 상태 | i < 3 | 모든 루프 반복 전에 확인됩니다. 거짓이면 루프가 중지됩니다. |
| 몸 | alert(i) | 조건이 참인 동안 계속해서 실행됩니다. |
| 단계 | i++ | 각 반복마다 본문 이후에 실행됩니다. |
일반적인 루프 알고리즘은 다음과 같이 작동합니다.
실행 시작 → (조건 → 실행 바디 및 실행 단계) → (조건 → 실행 바디 및 실행 단계) → (조건 → 실행 바디 및 실행 단계) → ...
즉, begin 한 번 실행된 다음 반복됩니다. 각 condition 테스트 후에 body 과 step 실행됩니다.
루프를 처음 사용하는 경우 예제로 돌아가서 종이에 단계별로 실행되는 방식을 재현하는 것이 도움이 될 수 있습니다.
우리의 경우에는 정확히 다음과 같은 일이 발생합니다.
// for (let i = 0; i < 3; i++) 경고(i)
// 실행 시작
내가 = 0이라고 하자
// 조건이 있는 경우 → 본문 실행 및 단계 실행
if (i < 3) { 경고(i); 나++ }
// 조건이 있는 경우 → 본문 실행 및 단계 실행
if (i < 3) { 경고(i); 나++ }
// 조건이 있는 경우 → 본문 실행 및 단계 실행
if (i < 3) { 경고(i); 나++ }
// ...완료, 이제 i == 3이기 때문입니다.인라인 변수 선언
여기서는 "카운터" 변수 i 루프에서 바로 선언됩니다. 이를 "인라인" 변수 선언이라고 합니다. 이러한 변수는 루프 내부에서만 표시됩니다.
for (let i = 0; i < 3; i++) {
경고(i); // 0, 1, 2
}
경고(i); // 오류, 해당 변수가 없습니다.변수를 정의하는 대신 기존 변수를 사용할 수 있습니다.
내가 = 0이라고 하자;
for (i = 0; i < 3; i++) { // 기존 변수 사용
경고(i); // 0, 1, 2
}
경고(i); // 3, 루프 외부에서 선언되었으므로 표시됩니다. for 의 모든 부분을 건너뛸 수 있습니다.
예를 들어, 루프 시작 시 아무것도 할 필요가 없으면 begin 생략할 수 있습니다.
여기처럼:
내가 = 0이라고 하자; // 이미 선언하고 할당했습니다.
for (; i < 3; i++) { // "시작"이 필요하지 않습니다.
경고(i); // 0, 1, 2
} step 부분을 제거할 수도 있습니다.
내가 = 0이라고 하자;
(; i < 3;) {
경고(i++);
} 이는 루프를 while (i < 3) 과 동일하게 만듭니다.
실제로 모든 것을 제거하여 무한 루프를 만들 수 있습니다.
을 위한 (;;) {
// 제한 없이 반복
} 두 개는 세미콜론 for 해당합니다 ; 존재해야 합니다. 그렇지 않으면 구문 오류가 발생합니다.
일반적으로 루프는 조건이 거짓이 되면 종료됩니다.
하지만 특별한 break 지시문을 사용하면 언제든지 강제로 종료할 수 있습니다.
예를 들어, 아래 루프는 사용자에게 일련의 숫자를 요청하며, 숫자가 입력되지 않으면 "끊어집니다".
합계 = 0으로 둡니다.
동안 (참) {
let value = +prompt("숫자를 입력하세요", '');
if (!value) 중단; // (*)
합계 += 값;
}
Alert( '합계: ' + 합 ); 사용자가 빈 줄을 입력하거나 입력을 취소하면 해당 줄 (*) 에서 break 지시문이 활성화됩니다. 루프를 즉시 중지하고 루프 뒤의 첫 번째 줄에 제어권을 전달합니다. 즉, alert .
"무한 루프 + 필요에 따라 break " 조합은 루프의 시작이나 끝이 아니라 루프 본문의 중간이나 여러 위치에서 루프의 조건을 확인해야 하는 상황에 적합합니다.
continue 지시문은 break 의 "가벼운 버전"입니다. 전체 루프가 중지되지는 않습니다. 대신, 현재 반복을 중지하고 루프가 새 반복을 시작하도록 강제합니다(조건이 허용하는 경우).
현재 반복을 마치고 다음 반복으로 넘어가고 싶다면 이를 사용할 수 있습니다.
아래 루프는 continue 홀수 값만 출력하는 데 사용됩니다.
for (let i = 0; i < 10; i++) {
// true인 경우 본문의 나머지 부분을 건너뜁니다.
if (i % 2 == 0) 계속;
경고(i); // 1, 그다음 3, 5, 7, 9
} i 값이 짝수인 경우 continue 지시문은 본문 실행을 중지하고 for (다음 숫자 사용)의 다음 반복으로 제어를 전달합니다. 따라서 alert 홀수 값에 대해서만 호출됩니다.
continue 지시문은 중첩을 줄이는 데 도움이 됩니다.
홀수 값을 표시하는 루프는 다음과 같습니다.
for (let i = 0; i < 10; i++) {
만약 (i % 2) {
경고(i);
}
} 기술적인 관점에서 이는 위의 예와 동일합니다. 물론 continue 사용하는 대신 if 블록으로 코드를 래핑할 수 있습니다.
그러나 부작용으로 인해 중첩 수준이 한 단계 더 생성되었습니다(중괄호 내부의 alert 호출). if 내부의 코드가 몇 줄보다 길면 전체적인 가독성이 떨어질 수 있습니다.
break/continue
표현식이 아닌 구문 구성은 삼항 연산자 ? 와 함께 사용할 수 없습니다. . 특히 break/continue 와 같은 지시문은 허용되지 않습니다.
예를 들어, 다음 코드를 사용하면:
만약 (i > 5) {
경고(i);
} 또 다른 {
계속하다;
}...그리고 물음표를 사용하여 다시 작성합니다.
(나는 > 5) ? 경고(i) : 계속; // 여기서 계속은 허용되지 않습니다.
...작동이 중지됩니다. 구문 오류가 있습니다.
이는 물음표 연산자를 사용하지 않는 또 다른 이유일 뿐입니다 ? if 대신에 .
때로는 여러 중첩 루프에서 한 번에 벗어나야 할 때도 있습니다.
예를 들어, 아래 코드에서는 i 와 j 반복하여 (0,0) 에서 (2,2) 까지의 좌표 (i, j) 를 묻는 메시지를 표시합니다.
for (let i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
let input = 프롬프트(`좌표 값 (${i},${j})`, '');
// 여기서 종료하여 완료(아래)로 돌아가려면 어떻게 해야 할까요?
}
}
Alert('완료!');사용자가 입력을 취소하면 프로세스를 중지하는 방법이 필요합니다.
input 후 일반적인 break 내부 루프만 중단합니다. 그것만으로는 충분하지 않습니다. 레이블 여러분, 구조하러 오세요!
레이블은 루프 앞에 콜론이 있는 식별자입니다.
labelName: for (...) {
...
} 아래 루프의 break <labelName> 문은 레이블로 분리됩니다.
외부: for (let i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
let input = 프롬프트(`좌표 값 (${i},${j})`, '');
// 빈 문자열이거나 취소된 경우 두 루프에서 모두 중단됩니다.
if (!input) 외부 중단; // (*)
// 값으로 뭔가를 합니다...
}
}
Alert('완료!'); 위 코드에서 break outer outer 라는 레이블을 위쪽으로 찾고 해당 루프에서 빠져나옵니다.
따라서 제어는 (*) 에서 alert('Done!') 으로 바로 이동합니다.
레이블을 별도의 줄로 이동할 수도 있습니다.
밖의:
for (let i = 0; i < 3; i++) { ... } continue 지시문은 레이블과 함께 사용할 수도 있습니다. 이 경우 코드 실행은 레이블이 지정된 루프의 다음 반복으로 이동합니다.
라벨은 어디에서나 "점프"를 허용하지 않습니다.
레이블을 사용하면 코드의 임의 위치로 이동할 수 없습니다.
예를 들어 다음과 같은 작업은 불가능합니다.
브레이크 라벨; // 아래 라벨로 점프합니다(작동하지 않음) 라벨: (...)에 대해
break 지시문은 코드 블록 내에 있어야 합니다. 기술적으로 레이블이 지정된 코드 블록은 모두 가능합니다. 예:
라벨: {
// ...
브레이크 라벨; // 작동
// ...
} ...그러나 위의 예에서 볼 수 있듯이 시간 break 의 99.9%가 루프 내부에서 사용됩니다.
continue 루프 내부에서만 가능합니다.
우리는 3가지 유형의 루프를 다루었습니다:
while – 각 반복 전에 조건을 확인합니다.
do..while – 각 반복 후에 조건이 확인됩니다.
for (;;) – 각 반복 전에 조건이 확인되며 추가 설정이 가능합니다.
"무한" 루프를 만들려면 일반적으로 while(true) 구문이 사용됩니다. 이러한 루프는 다른 루프와 마찬가지로 break 지시문을 사용하여 중지할 수 있습니다.
현재 반복에서 아무것도 하고 싶지 않고 다음 반복으로 전달하고 싶다면 continue 지시문을 사용할 수 있습니다.
루프 전에 break/continue 지원 레이블을 지정합니다. 레이블은 break/continue 중첩 루프를 탈출하여 외부 루프로 이동하는 유일한 방법입니다.
중요도: 3
이 코드에서 경고한 마지막 값은 무엇입니까? 왜?
i = 3이라고 하자;
동안 (i) {
경고( i-- );
}
대답: 1 .
i = 3이라고 하자;
동안 (i) {
경고( i-- );
} 모든 루프 반복은 i 1 씩 감소시킵니다. while(i) 검사는 i = 0 일 때 루프를 중지합니다.
따라서 루프의 단계는 다음 순서("루프 풀림")를 형성합니다.
i = 3이라고 하자; 경고(i--); // 3을 표시하고 i를 2로 감소시킵니다. Alert(i--) // 2를 표시하고 i를 1로 감소시킵니다. Alert(i--) // 1을 표시하고 i를 0으로 감소시킵니다. // 완료, while(i) 검사가 루프를 중지합니다.
중요도: 4
모든 루프 반복에 대해 출력되는 값을 기록한 다음 이를 솔루션과 비교하십시오.
두 루프 모두 동일한 값을 alert 합니까?
접두사 형식 ++i :
내가 = 0이라고 하자; while (++i < 5) 경고(i );
접미사 형식 i++
내가 = 0이라고 하자; while (i++ < 5) 경고(i );
이 작업은 비교에 사용될 때 접미사/접두사 형식이 어떻게 다른 결과로 이어질 수 있는지 보여줍니다.
1부터 4까지
내가 = 0이라고 하자; while (++i < 5) 경고(i );
첫 번째 값은 i = 1 입니다. ++i 먼저 i 증가시킨 다음 새 값을 반환하기 때문입니다. 따라서 첫 번째 비교는 1 < 5 이고 alert 1 표시됩니다.
그런 다음 2, 3, 4… 따르세요. 값이 차례로 표시됩니다. ++ 변수 앞에 있기 때문에 비교에서는 항상 증가된 값을 사용합니다.
마지막으로 i = 4 5 로 증가하고 while(5 < 5) 비교가 실패하며 루프가 중지됩니다. 따라서 5 표시되지 않습니다.
1부터 5까지
내가 = 0이라고 하자; while (i++ < 5) 경고(i );
첫 번째 값은 다시 i = 1 입니다. i++ 의 후위 형식은 i 증가시킨 다음 이전 값을 반환하므로 i++ < 5 비교에서는 ( ++i < 5 와 반대로) i = 0 사용합니다.
하지만 alert 호출은 별개입니다. 이는 증가 및 비교 후에 실행되는 또 다른 명령문입니다. 따라서 현재 i = 1 얻습니다.
그런 다음 2, 3, 4…
i = 4 에서 멈추자. 접두사 형식 ++i 이를 증가시키고 비교에 5 사용합니다. 하지만 여기에는 i++ 형식의 접미사가 있습니다. 따라서 i 5 로 증가시키지만 이전 값을 반환합니다. 따라서 비교는 실제로 while(4 < 5) – true이고 컨트롤은 계속 alert .
i = 5 값이 마지막 값입니다. 왜냐하면 다음 단계에서는 while(5 < 5) false이기 때문입니다.
중요도: 4
각 루프에 대해 표시할 값을 적어 두세요. 그런 다음 답변과 비교하십시오.
두 루프 모두 동일한 값을 alert 합니까?
접미사 형식:
for (let i = 0; i < 5; i++) 경고( i );
접두사 형식:
for (let i = 0; i < 5; ++i) 경고( i );
답은 두 경우 모두 0 부터 4 까지입니다.
for (let i = 0; i < 5; ++i) 경고( i ); for (let i = 0; i < 5; i++) 경고( i );
이는 for 알고리즘에서 쉽게 추론할 수 있습니다.
모든 것(시작) 전에 i = 0 일 때 한 번만 실행합니다.
i < 5 조건을 확인하세요.
true 인 경우 루프 본문을 실행하고, alert(i) 실행한 다음 i++ 실행합니다.
i++ 증분은 조건 확인(2)과 분리됩니다. 그것은 또 다른 진술일 뿐입니다.
증분에 의해 반환된 값은 여기서 사용되지 않으므로 i++ 와 ++i 사이에는 차이가 없습니다.
중요도: 5
for 루프를 사용하여 2 에서 10 까지의 짝수를 출력합니다.
데모 실행
for (let i = 2; i <= 10; i++) {
if (i % 2 == 0) {
경고(i);
}
} 나머지를 구하고 여기에서 균등성을 확인하기 위해 "모듈로" 연산자 % 사용합니다.
중요도: 5
동작을 변경하지 않고 for 루프를 while 으로 변경하는 코드를 다시 작성합니다(출력은 동일하게 유지되어야 함).
for (let i = 0; i < 3; i++) {
경고( `번호 ${i}!` );
}
내가 = 0이라고 하자;
동안 (i < 3) {
경고( `번호 ${i}!` );
나++;
}중요도: 5
100 보다 큰 숫자를 묻는 루프를 작성하세요. 방문자가 다른 번호를 입력하면 다시 입력하도록 요청하세요.
루프는 방문자가 100 보다 큰 숫자를 입력하거나 입력을 취소하거나 빈 줄을 입력할 때까지 숫자를 요청해야 합니다.
여기서는 방문자가 숫자만 입력한다고 가정할 수 있습니다. 이 작업에서는 숫자가 아닌 입력에 대해 특별한 처리를 구현할 필요가 없습니다.
데모 실행
숫자를 보자;
하다 {
num = 프롬프트("100보다 큰 숫자를 입력하시겠습니까?", 0);
} while (num <= 100 && num); 루프 do..while 은 두 검사가 모두 진실인 동안 반복됩니다.
num <= 100 인지 확인합니다. 즉, 입력된 값이 여전히 100 보다 크지 않습니다.
num 이 null 이거나 빈 문자열인 경우 && num 검사는 false입니다. 그런 다음 while 루프도 중지됩니다.
PS num 이 null 이면 num <= 100 이 true 이므로 두 번째 확인이 없으면 사용자가 취소를 클릭해도 루프가 중지되지 않습니다. 두 가지 확인이 모두 필요합니다.
중요도: 3
1 보다 큰 정수를 1 과 자기 자신 이외의 어떤 것으로도 나머지 없이 나눌 수 없으면 소수라고 합니다.
즉, n > 1 1 과 n 외에는 균등하게 나누어질 수 없는 경우 소수입니다.
예를 들어, 5 2 , 3 , 4 로 나머지 없이 나눌 수 없기 때문에 소수입니다.
2 부터 n 까지의 구간에서 소수를 출력하는 코드를 작성하세요.
n = 10 의 경우 결과는 2,3,5,7 입니다.
PS 코드는 모든 n 에 대해 작동해야 하며 고정 값에 대해 하드 튜닝되어서는 안 됩니다.
이 작업에는 많은 알고리즘이 있습니다.
중첩 루프를 사용해 보겠습니다.
간격 {의 각 i에 대해
1..i의 제수가 있는지 확인하세요.
그렇다면 => 값은 소수가 아닙니다.
아니요 => 값이 소수이면 표시합니다.
}라벨을 사용하는 코드:
n = 10이라고 하자;
다음프라임:
for (let i = 2; i <= n; i++) { // 각 i에 대해...
for (let j = 2; j < i; j++) { // 제수를 찾습니다..
if (i % j == 0) nextPrime을 계속합니다; // 소수가 아닙니다. 다음으로 가세요.
}
경고(i); // 소수
} 최적화할 수 있는 여지가 많습니다. 예를 들어, 2 에서 i 의 제곱근까지의 약수를 찾을 수 있습니다. 그러나 어쨌든 큰 간격에 대해 정말 효율적이기를 원한다면 접근 방식을 변경하고 이차 체, 일반 수 필드 체 등과 같은 고급 수학 및 복잡한 알고리즘에 의존해야 합니다.