하루 지나 풀면 더 오래 남습니다. 1~11단원을 마친 다음 날 풀어 보세요. 1~11단원에서 골고루 12문제를 섞었고, 어느 레슨의 문제인지는 정답을 펼쳐야 보입니다. 출력을 쓰는 문제는 빈칸과 줄바꿈까지 종이에 끝까지 쓴 뒤 정답을 펼치세요. 줄 수를 알려 주지 않는 문제는 마지막 줄까지 다 씁니다. 막히면 정답 앞의 힌트를 먼저 펼칩니다. 점수는 매기지 않습니다.
한 번에 다 풀 필요는 없습니다. 문제 1~11은 폰으로도 풀 수 있고(약 30~40분), 끝의 만들어 보기 하나는 컴퓨터에서 Node로 직접 돌려 봅니다.
마지막 문제는 비동기 응답에서 올바른 JSON만 골라 합계를 구하는 함수를 빈 데서 만들어 봅니다. 컴퓨터가 있으면 저장해 돌려 맞춰 보고, 폰으로만 본다면 문제에 적힌 값으로 내 코드를 한 줄씩 따라가 맞춰 봅니다. 실행 결과는 모두 Node 26으로 돌린 것입니다.
문제 1
무엇이 찍힐까요? 세 줄을 글자 그대로 쓰세요.
const fee = 0;
console.log('50' + 10);
console.log(fee || 3000);
console.log(fee ?? 3000);
힌트
+는 한쪽이 문자열이면 이어 붙이고, ||는 0을 거짓 같은 값으로 보지만 ??는 null과 undefined만 비었다고 봅니다.
정답
5010
3000
0- 2번 줄:
'50'이 문자열이므로'5010'이 됩니다. - 3번 줄: 숫자
0은 거짓 같은 값이라||는 오른쪽3000을 돌려줍니다. - 4번 줄:
??는0을 그대로 살려0을 돌려줍니다.
다시 볼 레슨: 글자를 수로: Number와 NaN · 참 같은 값과 ??
문제 2
배열에서 짝수만 골라 더한 값을 돌려주는 함수를 부릅니다. 출력되는 두 줄을 쓰세요.
function addEven(nums) {
let sum = 0;
for (const n of nums) {
if (n % 2 === 0) {
sum += n;
}
}
return sum;
}
const a = addEven([3, 4, 7, 6]);
console.log(a);
console.log(addEven([1, 5]));
힌트
첫 호출에서는 4와 6이 더해지고, 둘째 호출에서는 조건이 참인 값이 없어 초기값 0이 그대로 반환됩니다.
정답
10
0[3, 4, 7, 6]에서는 짝수4와6만 더해져10을 돌려줍니다.[1, 5]에서는 짝수가 없으므로0을 돌려줍니다.
다시 볼 레슨: for...of로 배열 돌기 · 돌려받은 값 쓰기
문제 3
객체에 이름표를 하나 더 붙인 것과 ...로 펼쳐 만든 새 객체를 비교합니다. 출력되는 한 줄을 쓰세요.
const a = { q: 2 };
const b = a;
const c = { ...a };
b.q = 5;
c.q = 9;
console.log(a.q, b.q, c.q);
힌트
const b = a;는 같은 객체를 가리키고, const c = { ...a };는 속성을 복사한 새 객체를 만듭니다(규칙 3).
정답
5 5 9b는a와 같은 객체를 가리키므로b.q = 5로 바꾸면a.q도5가 됩니다.c는 펼쳐서 새로 만든 별도의 객체이므로c.q = 9는c만 바꿉니다.
다시 볼 레슨: 객체를 넘기고 복사하기 · 배열 바꾸기와 복사 · 단축 속성과 나머지 모으기
문제 4
숫자 배열을 정렬하고 20보다 큰 값만 고릅니다. 출력되는 두 줄을 쓰세요.
const nums = [30, 5, 100];
const s1 = nums.toSorted();
const s2 = nums.toSorted(
(a, b) => a - b,
);
const big = s2.filter(
(n) => n > 20,
);
console.log(s1);
console.log(big);
힌트
비교 함수 없는 toSorted()는 글자 순서로 정렬하고, (a, b) => a - b를 넘긴 toSorted는 숫자 크기 순서로 정렬합니다.
정답
[ 100, 30, 5 ]
[ 30, 100 ]s1은 글자 첫 자'1','3','5'순서로 정렬되어[ 100, 30, 5 ]가 됩니다.s2는 숫자 크기순[ 5, 30, 100 ]이고, 여기서20보다 큰 값만 거르면[ 30, 100 ]이 됩니다.
다시 볼 레슨: 정렬: sort와 toSorted · map·filter·find
문제 5
구조 분해 할당의 기본값을 씁니다. 출력되는 두 줄을 쓰세요.
function calc({ p, c = 500 }) {
return p - c;
}
console.log(calc({ p: 4500 }));
console.log(
calc({ p: 4500, c: 1000 }),
);
힌트
c 속성이 없을(undefined) 때만 기본값 500이 쓰입니다.
정답
4000
3500- 첫 호출은
c가 없어 기본값500을 써서4000이 찍힙니다. - 둘째 호출은
c: 1000이 넘어와3500이 찍힙니다.
다시 볼 레슨: 구조 분해로 꺼내기 · 기본값 매개변수
문제 6
클로저 두 개를 만들고 바깥 변수 step을 바꾼 뒤 차례로 부릅니다. 출력되는 두 줄을 쓰세요.
let step = 1;
function makeUp(start) {
let n = start;
return () => {
n += step;
return n;
};
}
const up = makeUp(10);
console.log(up());
step = 5;
console.log(up());
힌트
안쪽 함수는 up이 가진 n 칸과 전역의 step 이름표를 기억합니다(규칙 5).
정답
11
16- 첫 번째
up()은10 + 1로n을11로 바꾸고11을 찍습니다. step = 5로 바뀐 뒤 두 번째up()은11 + 5로n을16으로 바꾸고16을 찍습니다.
다시 볼 레슨: 클로저: 만들어진 칸을 기억하는 함수
문제 7
부모 클래스 Card를 상속받은 VipCard의 메서드를 부릅니다. 출력되는 두 줄을 쓰세요.
class Card {
constructor(owner) {
this.owner = owner;
this.pt = 0;
}
add(n) {
this.pt += n;
}
}
class VipCard extends Card {
add(n) {
this.pt += n * 2;
}
}
이어서 두 카드를 만들어 점수를 올립니다.
const c = new Card('민지');
const v = new VipCard('준호');
c.add(10);
v.add(10);
console.log(c.owner, c.pt);
console.log(v.owner, v.pt);
힌트
c.add(10)은 Card의 add를, v.add(10)은 VipCard에서 다시 정의한 add를 실행합니다.
정답
민지 10
준호 20c는 일반Card라10이 더해지고,v는VipCard라10 * 2인20이 더해집니다.
다시 볼 레슨: 클래스와 new · 상속: extends와 super
문제 8
JSON 문자열 배열을 돌며 읽고, 수량이 0 이하이면 오류를 던집니다. 출력되는 세 줄을 쓰세요.
const raw = [
'{"q":2}', '{bad}',
'{"q":0}',
];
for (const s of raw) {
try {
const o = JSON.parse(s);
if (o.q <= 0) {
throw new Error('0 이하');
}
console.log('통과:', o.q);
} catch (e) {
console.log('실패:', e.name);
}
}
힌트
'{bad}'는 JSON.parse에서 SyntaxError가 나고, '{"q":0}'은 throw new Error(...)에서 Error가 납니다. catch는 e.name을 찍고 있습니다.
정답
통과: 2
실패: SyntaxError
실패: Error- 첫 바퀴는
통과: 2가 찍힙니다. - 둘째 바퀴는
JSON.parse가 던진 오류의 이름인실패: SyntaxError가 찍힙니다. - 셋째 바퀴는
new Error('수량 오류')의 이름(e.name)인실패: Error가 찍힙니다.
다시 볼 레슨: try와 catch · throw로 오류 알리기
문제 9
다음 코드를 실행했을 때 출력되는 줄을 마지막 줄까지 순서대로 쓰세요.
console.log(1);
setTimeout(() => {
console.log(2);
}, 0);
Promise.resolve()
.then(() => {
console.log(3);
})
.then(() => {
console.log(4);
});
console.log(5);
힌트
지금 도는 코드(1, 5) → Promise 줄(3, 4) → 할 일 줄(2) 순서로 실행됩니다(규칙 8).
정답
1
5
3
4
2- 동기 코드인
1과5가 먼저 찍힙니다. - 이어서 Promise 줄의
3과4가 모두 찍힌 뒤, 할 일 줄의2가 마지막에 찍힙니다.
다시 볼 레슨: 타이머와 Promise, 누가 먼저
문제 10
async 함수 안에서 응답 본문을 꺼내 출력합니다. 출력되는 세 줄을 순서대로 쓰세요.
async function show() {
console.log('요청');
const res = Response.json({
item: '쿠키',
});
const d = await res.json();
console.log('도착:', d.item);
}
show();
console.log('대기');
힌트
show() 안에서 await 앞의 '요청'은 바로 찍히고, await res.json()에서 show 함수가 멈춘 동안 바깥의 '대기'가 먼저 찍힙니다.
정답
요청
대기
도착: 쿠키show()를 부르면'요청'이 먼저 찍히고,await res.json()에서 잠시 멈춥니다.- 바깥의
'대기'가 찍힌 뒤show가 다시 이어져'도착: 쿠키'를 찍습니다.
다시 볼 레슨: async와 await · fetch로 데이터 받아 오기
문제 11
아이디가 0일 때 던진 '없음' 오류를 catch에서 잡아 '없음' 한 줄이 찍혀야 하는데, 아래 코드는 catch가 잡지 못하고 멈췄습니다. 몇 번 줄을 어떻게 고쳐야 할까요? 한 줄만 고쳐, 고친 줄을 쓰세요.
async function findUser(id) {
if (id === 0) {
throw new Error('없음');
}
return '민지';
}
try {
findUser(0);
} catch (e) {
console.log(e.message);
}
main.js:3 throw new Error('없음'); ^ Error: 없음 at findUser (main.js:3:11) at main.js:8:3힌트
8번 줄에서 findUser(0)이 돌려준 거부된 Promise를 try 안에서 오류로 풀려면 앞에 무엇을 붙여야 하는지 보세요.
정답
8번 줄을 await findUser(0);으로 고칩니다.
async function findUser(id) {
if (id === 0) {
throw new Error('없음');
}
return '민지';
}
try {
await findUser(0);
} catch (e) {
console.log(e.message);
}없음try안에서await를 붙여야 거부된Promise가 오류로 던져져catch (e)에 잡힙니다.
다시 볼 레슨: 기다리는 일의 오류
문제 12 (만들어 보기)
이번에는 1~11단원에서 배운 것을 한데 모아 빈 데서 함수를 만들어 봅니다. JSON 문자열을 담은 Promise들의 배열 tasks를 받아:
await Promise.all(tasks)로 모든 문자열 배열을 한꺼번에 꺼냅니다.- 배열의 문자열을 하나씩 돌며
try / catch와JSON.parse로 읽습니다. - 올바른 JSON이면 객체의
p속성을 합계에 더하고, 깨진 JSON이면 건너뛰어 최종 합계를 돌려주는async함수sumOk(tasks)를 작성하세요.
이렇게 나와야 합니다.
7500
시험 배열을 [Promise.resolve('{bad}')] 하나로 바꾸면 0이 나와야 합니다.
0
아래 칸의 위쪽에 sumOk 함수를 쓰세요.
// async 함수 sumOk 쓰기
const tasks = [
Promise.resolve('{"p":4500}'),
Promise.resolve('{bad}'),
Promise.resolve('{"p":3000}'),
];
console.log(await sumOk(tasks));
힌트
async function sumOk(tasks) 안에서 await Promise.all(tasks)로 문자열 배열을 받은 뒤, for...of와 try / catch로 JSON.parse(s)를 실행해 o.p를 더하고 합계를 돌려줍니다.
정답
모범 답입니다.
async function sumOk(tasks) {
const list =
await Promise.all(tasks);
let sum = 0;
for (const s of list) {
try {
const o =
JSON.parse(s);
sum += o.p;
} catch (e) {
sum += 0;
}
}
return sum;
}이어서 시험 데이터를 넣어 확인합니다.
const t1 = '{"p":4500}';
const t2 = '{bad}';
const t3 = '{"p":3000}';
const tasks = [
Promise.resolve(t1),
Promise.resolve(t2),
Promise.resolve(t3),
];
const res =
await sumOk(tasks);
console.log(res);7500다시 볼 레슨: fetch로 데이터 받아 오기 · try와 catch · JSON: 객체와 글 사이
틀린 문제는 그 레슨으로 돌아가 모션 그림과 '자주 틀리는 곳'을 보고, 하루쯤 지난 뒤 그 문제만 다시 풀어 보세요. 그날 바로 다시 풀면 방금 본 정답이 기억나 맞힌 것인지 알기 어렵습니다.