본문으로 건너뛰기

단원 1~5 섞어 풀기

자바스크립트 목차반복문제 12개

하루 지나 풀면 더 오래 남습니다. 1~5단원을 마친 다음 날 풀어 보세요. 1~5단원에서 골고루 12문제를 섞었고, 어느 레슨의 문제인지는 정답을 펼쳐야 보입니다. 출력을 쓰는 문제는 빈칸과 줄바꿈까지 종이에 끝까지 쓴 뒤 정답을 펼치세요. 줄 수를 알려 주지 않는 문제는 마지막 줄까지 다 씁니다. 막히면 정답 앞의 힌트를 먼저 펼칩니다. 점수는 매기지 않습니다.

한 번에 다 풀 필요는 없습니다. 문제 1~11은 폰으로도 풀 수 있고(약 30~40분), 끝의 만들어 보기 하나는 컴퓨터에서 Node로 직접 돌려 봅니다.

5번과 11번은 긴 코드입니다. 추적 표(줄 · 바뀐 이름 · 값 · 출력)를 그리며 따라가세요. 마지막 문제는 도장 계산기를 빈 데서 만들어 봅니다. 컴퓨터가 있으면 저장해 돌려 맞춰 보고, 폰으로만 본다면 문제에 적힌 값으로 내 코드를 한 줄씩 따라가 맞춰 봅니다. 실행 결과는 모두 Node 26으로 돌린 것입니다.

문제 1

무엇이 찍힐까요? 네 줄을 글자 그대로 쓰세요.

const a = '12';
const b = 3;
console.log(a + b);
console.log(a * b);
console.log(a > '9');
console.log(Number(a) > 9);
힌트

줄마다 기호 양쪽 값의 종류를 먼저 가르세요.

정답
실행 결과
123
36
false
true
  • 3번 줄: +의 한쪽이 글자라 3을 글자로 바꿔 이어 '123'입니다.
  • 4번 줄: *는 '12'를 수로 바꿔 곱해 36입니다.
  • 5번 줄: 글자끼리라 첫 글자 '1'과 '9'를 견주고, '1'이 앞이라 false입니다.
  • 6번 줄: Number()가 만든 수 12와 9를 견주어 true입니다.

흔한 오답은 첫 줄의 15와 셋째 줄의 true입니다. 따옴표 안의 12도 수로 더하고 견준다고 본 것입니다(문자열과 수를 가리지 않는 생각). 수로 견주려면 6번 줄처럼 먼저 수를 만듭니다.

다시 볼 레슨: 수·글자·불리언과 typeof · 같음과 비교 · 글자를 수로: Number와 NaN

문제 2

주문을 고칩니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.

let cup = '라테';
let order = cup;
cup = '녹차';
order = order + ' 2잔';
console.log(cup);
console.log(order);
힌트

줄마다 이름 cup과 order가 어느 값에 붙는지 이름표를 옮겨 그려 보세요.

정답
실행 결과
녹차
라테 2잔
  • 2번 줄: order를 cup이 붙은 바로 그 '라테'에 붙입니다.
  • 3번 줄: cup만 '녹차'에 다시 붙습니다. order는 '라테'에 그대로 붙어 있습니다.
  • 4번 줄: '라테' 뒤에 ' 2잔'을 이은 새 값에 order를 다시 붙입니다.

흔한 오답은 둘째 줄의 녹차 2잔입니다. order가 이름 cup을 따라 움직인다고 본 것입니다. 첫 줄을 라테녹차로 쓰면 cup을 값이 쌓이는 상자로 본 것입니다(상자 생각). 다시 붙이면 그 이름의 옛 연결만 끊기고, 같은 값에 붙은 다른 이름은 그대로입니다(규칙 3).

다시 볼 레슨: 이름표 다시 붙이기와 const · 문자열 잇기와 길이

문제 3

에스프레소 샷이 2개보다 적으면 2개를 더하고, 아니면 하나를 빼려고 두 갈래를 썼습니다. 무엇이 찍힐까요? 한 줄을 글자 그대로 쓰세요.

let shots = 1;
if (shots < 2) {
  shots = shots + 2;
}
if (shots >= 2) {
  shots = shots - 1;
}
console.log(shots);
힌트

5번 줄의 if가 앞 if에 이어져 있는지, 따로 서 있는지 보세요.

정답
실행 결과
2
  • 2·3번 줄: 1 < 2가 참이라 shots가 3에 다시 붙습니다.
  • 5·6번 줄: 따로 선 if라 지금의 shots로 조건을 새로 계산합니다. 3 >= 2가 참이라 shots가 2에 다시 붙습니다.

흔한 오답은 3입니다. 따로 선 둘째 if를 앞 if의 else처럼 본 것입니다(else를 if 하나 더로 보는 생각). 둘 가운데 하나만 실행하려면 4~5번 줄을 } else {로 잇습니다. 그러면 정말 3이 찍힙니다.

다시 볼 레슨: if와 else

문제 4

잔 수가 3잔 이상이면 '많음' 깃발을 세운 뒤, 주문을 1잔으로 고쳤습니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.

let cups = 3;
const many = cups >= 3;
cups = 1;
console.log(many);
console.log(cups >= 3);
힌트

2번 줄의 비교가 언제 true나 false로 접히는지 보세요.

정답
실행 결과
true
false
  • 2번 줄: 그때 cups는 3이라 3 >= 3이 true로 접히고, many가 그 값에 붙습니다.
  • 3번 줄: cups만 1에 다시 붙습니다. many는 다시 계산되지 않습니다.
  • 5번 줄: 지금의 cups로 새로 견주어 1 >= 3은 false입니다.

흔한 오답은 첫 줄의 false입니다. 2번 줄이 비교식을 저장해 두었다가 찍을 때 다시 계산한다고 본 것입니다(식이 저장된다는 생각). 오른쪽은 대입하는 그때 한 번 계산합니다(규칙 2).

다시 볼 레슨: 변수: let으로 이름 붙이기 · 같음과 비교

문제 5

포인트 이벤트입니다. 날마다 그날 번호만큼 포인트를 주고, 짝수 날에는 두 배를 줍니다. 20점이 안 되는 동안 날마다 찍습니다. 무엇이 찍힐까요? 마지막 줄까지 글자 그대로 쓰세요.

let day = 1;
let point = 0;
while (point < 20) {
  if (day % 2 === 0) {
    point = point + day * 2;
  } else {
    point = point + day;
  }
  console.log(day, point);
  day = day + 1;
}
힌트

바퀴마다 3번 줄의 조건 → 4번 줄의 조건 → point → 출력 → day 차례로 추적 표에 적습니다.

정답

모두 다섯 줄입니다.

실행 결과
1 1
2 5
3 8
4 16
5 21

바퀴마다 한 줄로 줄인 추적 표입니다. 실행되는 줄마다 한 줄씩 쓰면 28줄입니다.

바퀴point < 20day % 2 === 0point출력day
10 → truefalse11 12
21 → truetrue52 53
35 → truefalse83 84
48 → truetrue164 165
516 → truefalse215 216
—21 → false반복 끝

다섯째 바퀴는 16으로 시작해 조건이 참이라 덩어리로 들어가고, 그 안에서 point가 21에 붙어도 9번 줄까지 마저 찍습니다.

흔한 오답은 5 21을 빼고 네 줄만 쓰는 것입니다. point가 20을 넘는 순간 반복이 멈춘다고 본 것입니다(조건을 늘 지켜본다는 생각). 짝수 날의 두 배를 놓쳐 모두 그날 번호만큼 더하면 2 3부터 어긋납니다.

다시 볼 레슨: while과 추적 표 · if와 else · 사칙 계산과 나머지

문제 6

낱말 'mango'에서 글자를 꺼냅니다. 무엇이 찍힐까요? 마지막 줄까지 글자 그대로 쓰세요.

const s = 'mango';
const n = s.length;
let t = '';
for (let i = 2; i <= n; i++) {
  t = t + (s[i] ?? '-');
}
console.log(s.slice(2, 4));
console.log(t);
힌트

'mango'의 글자마다 자리 번호를 0부터 적고, 반복이 마지막에 꺼내는 자리가 있는 칸인지 보세요.

정답

모두 두 줄입니다.

실행 결과
ng
ngo-
  • 7번 줄: slice(2, 4)는 2번 'n'과 3번 'g'만 꺼냅니다. 끝 번호 4의 'o'는 들지 않습니다.
  • 4~6번 줄: i가 2, 3, 4일 때 'n' · 'g' · 'o'를 잇습니다. i <= n이라 i가 5일 때도 한 바퀴 더 돌고, 다섯 글자의 번호는 0~4뿐이라 s[5]는 오류 없이 undefined입니다. ?? 연산자가 그 자리에 '-'를 넣어 'ngo-'가 됩니다.

흔한 오답은 첫 줄의 ngo입니다. 자르기에 끝 번호의 글자도 든다고 본 것입니다(끝도 든다는 생각). 둘째 줄을 ngo로 쓰면 <= 연산자의 마지막 바퀴를 놓친 것이고, 오류로 멈춘다고 쓰면 없는 자리를 꺼내면 바로 오류가 난다고 본 것입니다(없으면 오류라는 생각).

다시 볼 레슨: 인덱스와 자르기 · for의 세 칸 · 참 같은 값과 ??

문제 7

쿠키 17개를 다섯 명에게 똑같이 나눠 줍니다. 무엇이 찍힐까요? 세 줄을 글자 그대로 쓰세요.

const total = 17;
const each = total / 5;
console.log(each);
console.log(Math.floor(each));
console.log(total % 5);
힌트

2번 줄에서 each가 어떤 값에 붙는지 먼저 정하세요.

정답
실행 결과
3.4
3
2
  • 2·3번 줄: /는 소수점 아래까지 나눠 each가 3.4에 붙고, 3번 줄이 그 값을 찍습니다.
  • 4번 줄: Math.floor()가 소수점 아래를 내린 3을 냅니다. 한 사람 몫입니다.
  • 5번 줄: 17을 5로 나눈 나머지 2입니다. 남는 쿠키입니다.

흔한 오답은 첫 줄의 3입니다. /가 몫을 낸다고 본 것입니다(/가 몫이라는 생각). 몫은 Math.floor()로 내려서 얻습니다.

다시 볼 레슨: 사칙 계산과 나머지

문제 8

세 바퀴를 돌며 바퀴 번호를 찍으려 합니다. 이 코드를 실행하면 어떻게 될까요? 알맞은 것을 고르세요.

let count = 0;
for (let i = 0; i < 3; i++)
  count = count + 1;
  console.log(i);
console.log(count);
  • ① 0 · 1 · 2 · 3을 차례로 찍는다
  • ② 3 · 3을 차례로 찍는다
  • ③ 아무것도 찍지 않고 4번 줄에서 ReferenceError로 멈춘다
  • ④ 아무것도 찍지 않고 SyntaxError로 멈춘다
힌트

2번 줄부터 한 줄씩, 그 줄이 몇 번 실행되는지 적어 보세요.

힌트 둘

2번 줄의 for에 드는 문장이 어디까지인지 중괄호로 보세요. 그다음 4번 줄에 i가 있는지 봅니다.

정답

③ — 실행 결과는 이렇습니다.

실행 결과
main.js:4  console.log(i);              ^ ReferenceError: i is not defined    at main.js:4:15

중괄호가 없으면 for에는 바로 뒤 문장 하나(3번 줄)만 듭니다. 세 바퀴 동안 count만 1씩 커지고, 들여 쓴 4번 줄은 반복 밖입니다. 반복 머리에서 만든 i는 반복 밖에 없어 4번 줄이 ReferenceError로 멈춥니다. 그 앞에 찍은 줄이 없어 화면에는 오류뿐이고, at main.js:4:15 줄이 실행 중 오류라는 표시입니다.

  • ① 들여 쓴 두 줄이 다 반복에 든다고 봤습니다(들여쓰기가 덩어리라는 생각). 덩어리는 중괄호가 정합니다(규칙 4).
  • ② 반복이 끝나도 i가 3에 붙은 채 남는다고 봤습니다. let i는 그 반복 안에서만 삽니다.
  • ④ 중괄호가 없으면 문법 오류라고 봤습니다. 중괄호 없이 바로 뒤 문장 하나만 드는 꼴은 if처럼 for도 문법에 맞습니다.

파이썬에서는 들여 쓴 줄이 모두 반복에 들고 반복 뒤에 i가 남습니다 — 자바스크립트는 중괄호가 없으면 바로 뒤 한 문장만 들고, let i는 반복 밖에 없습니다.

다시 볼 레슨: for의 세 칸 · if와 else · 오류 메시지 읽기

문제 9

10월 15일에서 그달 마지막 날(31일)까지 남은 날을 세려 했는데 남은 날 NaN이 찍혔습니다. 이름마다 찍는 줄을 넣어 돌렸더니 이렇게 찍혔습니다. 예측과 처음 갈리는 줄은 몇 번 줄이고, 그 줄을 어떻게 고쳐야 할까요?

const date = '10-15';
const day = date[4] + date[5];
console.log('day', day);
const left = 31 - day;
console.log('left', left);
실행 결과
day 5undefined
left NaN
힌트

day의 예측은 '15'입니다. '10-15'의 글자마다 자리 번호를 0부터 적어 보세요.

정답

2번 줄입니다. day의 예측은 '15'인데 '5undefined'가 찍혀 여기서 처음 갈립니다. const day = date.slice(3);⁠으로 고칩니다. 찍어 본 줄을 지우고 남은 날을 찍으면 이렇습니다.

const date = '10-15';
const day = date.slice(3);
const left = 31 - day;
console.log('남은 날', left);
실행 결과
남은 날 16

'10-15'는 다섯 글자라 번호가 0~4이고, '15'는 3번과 4번입니다. 고치기 전의 date[5]는 없는 자리라 오류 없이 undefined였고, +가 '5'와 그것을 이어 '5undefined'를 만들었습니다. 그 글은 수로 바꿀 수 없어 4번 줄의 빼기가 NaN을 냈습니다. 고친 뒤 3번 줄의 31 - '15'는 빼기가 글자를 수로 바꿔 16입니다.

  • 다르게 고쳐도 되는 곳: date[3] + date[4] · date.slice(-2) · date.slice(3, 5)도 '15'를 만들어 16이 찍힙니다.
  • 흔한 오답은 NaN이 찍힌 4번 줄을 고치는 것입니다. 4번 줄을 31 - Number(day)로 바꿔도 Number('5undefined')가 NaN이라 그대로입니다. 틀린 값이 찍힌 줄이 아니라, 거슬러 올라가 예측과 처음 갈린 줄을 고칩니다. 없는 자리는 꺼낸 줄에서 멈추지 않고 undefined를 주어, 틀린 값이 다음 줄로 조용히 흘러갑니다(없으면 오류라는 생각).

다시 볼 레슨: 값을 찍어 보며 고치기 · 인덱스와 자르기

문제 10

낱말 'kiwi'에 든 'i'를 세려고 썼습니다. 무엇이 찍힐까요? 한 줄을 글자 그대로 쓰세요.

const word = 'kiwi';
let count = 0;
for (let i = 0; i < 4; i++) {
  if (word[i] === 'i') {
    count = i;
  }
}
console.log(count);
힌트

5번 줄이 count를 무엇에 붙이는지, 'i'가 있는 자리 번호마다 적어 보세요.

정답
실행 결과
3

'kiwi'에서 'i'는 1번과 3번 자리입니다. 5번 줄은 그때마다 count를 자리 번호 i에 다시 붙일 뿐이라, 마지막 'i'의 자리 3이 남습니다.

흔한 오답은 2입니다. 이름이 count이니 자바스크립트가 알아서 센다고 본 것입니다(이름이 뜻을 정한다는 생각). 세려면 5번 줄을 count = count + 1;로 씁니다. 그러면 정말 2가 찍힙니다(규칙 6).

다시 볼 레슨: 합 모으기와 세기

문제 11

1부터 세며 3의 배수는 건너뛰고 더하다가, 합이 8을 넘으면 멈춥니다. 무엇이 찍힐까요? 마지막 줄까지 글자 그대로 쓰세요.

let total = 0;
for (let i = 1; i < 10; i++) {
  if (i % 3 === 0) {
    console.log('건너뜀', i);
    continue;
  }
  total = total + i;
  if (total > 8) {
    break;
  }
}
console.log('합', total);
힌트

바퀴마다 i · 3번 줄의 조건 · total · 8번 줄의 조건을 추적 표에 적고, continue와 break를 만난 바퀴에서 다음에 어디로 가는지 봅니다.

정답

모두 두 줄입니다.

실행 결과
건너뜀 3
합 12

바퀴마다 한 줄로 줄인 추적 표입니다. 실행되는 줄마다 한 줄씩 쓰면 28줄입니다.

ii % 3 === 0totaltotal > 8출력 · 다음
1false1false
2false3false
3true(건너뜀)건너뜀 3 · continue
4false7false
5false12truebreak
—합 12

셋째 바퀴는 continue가 7~10번 줄을 건너뛰고 바꾸기 칸으로 가, 반복은 4로 이어집니다. 다섯째 바퀴에서 합이 12가 되어 break로 반복을 끝내므로 6부터는 보지 않습니다.

흔한 오답 하나는 건너뜀 3과 합 3입니다. continue가 반복을 끝낸다고 본 것입니다. continue는 이번 바퀴만 건너뜁니다. 다른 하나는 건너뜀 6 · 건너뜀 9까지 찍고 합 27로 쓰는 것입니다. 8을 넘은 바퀴의 break를 놓쳐 끝까지 센 것입니다.

다시 볼 레슨: break와 continue · for의 세 칸

문제 12 (만들어 보기)

도장 계산기를 빈 데서 만들어 봅니다. 하루 한 잔씩 마시고 날마다 도장을 하나 찍습니다. 도장이 8개가 되는 날 무료 한 잔을 주고 도장을 0으로 되돌립니다. 무료인 날마다 무료 8처럼 그날 번호를 찍고, 끝에 남은 도장 수와 받은 무료 잔 수를 찍습니다. 날 수는 const n = 18;로 두고 시작합니다. 이렇게 나와야 합니다.

무료 8
무료 16
도장 2
무료 잔 2

다 쓰면 날 수를 7로 바꿔 따라가 봅니다. 도장 7과 무료 잔 0 두 줄만 나와야 합니다. 24로 바꾸면 무료 8 · 무료 16 · 무료 24 · 도장 0 · 무료 잔 3이 나와야 합니다.

힌트

도장 계산기의 하위 목표 넷(1. 도장을 0으로 · 2. 날마다 하나 찍기 · 3. 열 개면 무료·0으로 · 4. 끝나고 쓰기)에서 열 개를 여덟 개로 바꿉니다. 무료 잔 수는 세기 틀대로 반복 앞에서 0에 붙이고, 무료인 날 1을 더하고, 끝에서 찍습니다.

정답

모범 답입니다. 주석은 줄 폭 때문에 뺐습니다 — 2~3번 줄이 '1. 도장을 0으로'(무료 잔 수도 함께), 4~13번 줄이 '2. 날마다 하나 찍기', 그 안의 7~11번 줄이 '3. 여덟 개면 무료·0으로', 14~15번 줄이 '4. 끝나고 쓰기'입니다.

const n = 18;
let stamps = 0;
let free = 0;
let i = 1;
while (i <= n) {
  stamps = stamps + 1;
  if (stamps === 8) {
    console.log('무료', i);
    stamps = 0;
    free = free + 1;
  }
  i++;
}
console.log('도장', stamps);
console.log('무료 잔', free);
실행 결과
무료 8
무료 16
도장 2
무료 잔 2

날 수가 7이면 도장이 8개에 닿지 않아 도장 7 · 무료 잔 0이고, 24면 마지막 날에 무료가 되어 도장이 0으로 돌아가 도장 0 · 무료 잔 3입니다.

  • 다르게 써도 되는 곳: 반복을 for (let i = 1; i <= n; i++) 한 줄로 써도 됩니다(모범 답은 폰 화면 폭 때문에 while로 나눴습니다). 무료 잔 수는 free += 1;로 더해도 됩니다.
  • 찍은 화면이 위와 같고 둘째 · 셋째 시험 값(7 · 24)도 맞으면 맞습니다.
  • 흔한 오답 하나는 stamps = 0;을 if 덩어리 밖에 두는 것입니다. 날마다 0으로 돌아가 무료가 한 번도 찍히지 않고 도장 0 · 무료 잔 0이 찍힙니다(규칙 4).
  • 조건을 stamps > 8로 쓰면 9개가 된 날에야 걸려 무료 9 · 무료 18이 찍힙니다. 무료 잔 수를 세는 줄을 if 덩어리 밖에 두면 날마다 세어 무료 잔 18이 찍힙니다.

다시 볼 레슨: 도장 계산기 만들기 · 합 모으기와 세기

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

자바스크립트 목차로