함수가 return으로 돌려준 값은 함수를 부른 자리에 놓입니다. 그 값에 이름을 붙이거나 식과 다른 함수의 인자로 쓸 수 있고, return을 만나면 함수는 그 자리에서 끝납니다.
console.log로 찍기만 하는 함수는 결과를 화면에 보여 줄 뿐이라, 그 결과로 다시 계산할 수 없습니다. 값을 돌려받아야 합계에 더하고 다른 함수에 넘길 수 있습니다.
이 레슨에서는 돌려받은 값이 식 안에서 어떻게 쓰이는지와, return이 함수를 언제 끝내는지 봅니다.
1돌려받은 값은 부른 자리에 놓인다
그림의 코드입니다.
function price(n) {
return 4000 * n;
console.log('계산 끝');
}
const total = price(2) + 500;
6번 줄은 오른쪽 식 price(2) + 500부터 계산합니다(규칙 2). 먼저 price(2)를 부르면 새 칸에서 n이 2에 붙고, 2번 줄이 4000 * n을 계산한 8000을 돌려줍니다(규칙 5). 돌려받은 8000이 price(2)가 있던 자리에 놓여 식은 8000 + 500이 되고, 8500으로 접힙니다. total은 8500에 붙습니다.
돌려받은 값은 이렇게 식에 쓰거나, 이름을 붙이거나, 다른 함수에 인자로 넘길 수 있습니다. 아래 코드는 무엇을 찍을까요? 마지막 줄까지 정한 뒤 펼쳐 보세요.
function price(n) {
return 4000 * n;
}
const total = price(2) + 500;
console.log(total);
console.log(price(3));
price(1);
실행 결과 보기
8500
12000예상과 다르면 그곳이 배울 곳입니다.
7번 줄은 price(3)이 돌려준 12000을 console.log에 인자로 넘겨 찍습니다. 8번 줄도 price를 불러 4000을 돌려받지만, 그 값을 찍지도 이름을 붙이지도 않아 화면에는 아무것도 나오지 않습니다.
4000이 한 줄 더 찍힌다고 예상했다면, 돌려준 값이 화면에 저절로 나온다고 본 것입니다. 화면에 쓰는 것은 console.log뿐입니다(규칙 5).
2return을 만나면 함수는 바로 끝난다
그림 코드의 3번 줄 console.log('계산 끝');은 한 번도 실행되지 않습니다. return은 값을 돌려주면서 함수를 그 자리에서 끝내, 실행은 3번 줄로 가지 않고 부른 6번 줄로 돌아갑니다.
반복 안에서 만나도 같습니다. 1부터 n까지 더하려던 함수인데, sum(3)이 6이 아니라 1을 찍습니다.
function sum(n) {
let total = 0;
for (let i = 1; i <= n; i++) {
total = total + i;
return total;
}
}
console.log(sum(3));
1첫 바퀴에서 total이 1에 다시 붙자마자 5번 줄의 return이 1을 돌려주고 함수가 끝납니다. 반복이 남아 있어도 둘째 바퀴는 오지 않습니다. 합을 다 모은 뒤 돌려주려면 return을 반복이 끝난 뒤에 둡니다.
3return이 없는 함수의 값은 undefined다
return 없이 console.log만 하는 함수는 undefined를 돌려줍니다. 그 값을 글자처럼 쓰면 오류가 납니다.
function clean(text) {
console.log(text.trim());
}
const item = clean(' latte ');
console.log(item.toUpperCase());
lattemain.js:6console.log(item.toUpperCase()); ^ TypeError: Cannot read properties of undefined (reading 'toUpperCase') at main.js:6:18latte는 2번 줄이 화면에 쓴 것이고, clean이 돌려준 것은 undefined입니다. TypeError로 시작하는 줄은 'undefined의 속성을 읽을 수 없다(toUpperCase를 읽으려 함)', 곧 undefined에서 메서드를 꺼내려 했다는 뜻입니다.
오류는 6번 줄에서 났지만 고칠 곳은 2번 줄입니다. console.log(text.trim());을 return text.trim();으로 바꾸면 item이 'latte'에 붙고, 6번 줄이 LATTE를 찍습니다.
예제
돌려받은 값끼리 더하기
메뉴 값을 받아 500원 할인한 값을 돌려주는 함수입니다.
// 1. 받을 값 정하기
function sale(won) {
// 2. 계산하기
const off = won - 500;
// 3. 돌려주기
return off;
}
const coffee = sale(4000);
const latte = sale(4500);
console.log(coffee + latte);
75009번 줄과 10번 줄은 돌려받은 3500과 4000에 이름을 붙이고, 11번 줄이 두 값을 더해 찍습니다. 값을 돌려주는 함수라서 결과로 계속 계산할 수 있습니다.
자주 틀리는 곳
틀린 생각: return 대신 console.log를 써도 값이 부른 자리로 돌아온다.
화면에 값이 보이니 함수가 그 값을 내놓은 것처럼 보입니다. 3절의 clean처럼 찍기만 한 함수가 돌려주는 것은 undefined입니다.
맞는 규칙: 부른 자리로 값을 보내는 것은 return이고, console.log만 한 함수는 undefined를 돌려줍니다(규칙 5).
틀린 생각: return 뒤에 쓴 줄도 함수가 끝나기 전에 실행된다.
return 아래에 줄이 더 있으니 그 줄까지 실행한 뒤 함수가 끝날 것처럼 보입니다. 그림 코드의 3번 줄과 2절의 둘째 바퀴처럼, return을 만난 뒤의 줄은 실행되지 않습니다.
맞는 규칙: return은 값을 돌려주며 함수를 그 자리에서 끝냅니다. 함수가 할 일은 모두 return 앞에 씁니다(규칙 5).
틀린 생각: return과 돌려줄 식은 다른 줄에 나눠 써도 된다.
긴 식은 줄을 나눠 써 왔으니, return 뒤에서 줄을 바꿔도 될 것 같습니다.
function price(n) {
return
4000 * n;
}
console.log(price(2));
undefined자바스크립트는 return 바로 뒤에서 줄이 바뀌면 그 줄 끝에 ;이 있는 것으로 읽어, 아무 값 없이 함수를 끝냅니다. 3번 줄은 실행되지 않습니다.
맞는 규칙: 돌려줄 식은 return과 같은 줄에서 시작합니다. return만 쓴 줄은 undefined를 돌려줍니다.
틀린 생각: 함수가 돌려준 값은 화면에 저절로 나온다.
부르면 결과가 생기니 어딘가에 보일 것 같습니다. 1절 맞혀 보기의 8번 줄 price(1);은 4000을 돌려받지만 아무것도 찍지 않았습니다.
맞는 규칙: 돌려받은 값은 부른 자리에 놓일 뿐이고, 화면에 쓰는 것은 console.log입니다. 값을 보려면 console.log(price(1))처럼 찍습니다(규칙 5).
확인 문제
1. 1절 둘째 코드의 5번 줄에서 500 대신 price(1)을 더하고 이름을 won으로 바꾼 뒤, 7번 줄과 8번 줄을 지웠습니다. 무엇이 찍힐까요? 마지막 줄까지 글자 그대로 쓰세요.
function price(n) {
return 4000 * n;
}
const won = price(2) + price(1);
console.log(won);
힌트
5번 줄의 두 부르기가 각각 무엇을 돌려주는지 적고, 그 값을 부른 자리에 놓아 식을 계산합니다.
정답
모두 1줄입니다.
12000price(2)가 8000을, price(1)이 4000을 돌려주어 식이 8000 + 4000이 됩니다. 부를 때마다 새 칸이 생겨 n이 2와 1에 따로 붙습니다.
흔한 오답은 8000과 4000이 먼저 찍힌 세 줄입니다. 돌려준 값이 화면에 저절로 나온다고 본 것입니다. 돌려받은 값은 부른 자리에 놓여 식에 쓰일 뿐이고, 화면에 쓰는 것은 6번 줄의 console.log입니다(규칙 5).
2. 1부터 n까지 더해 돌려주는 함수 sum의 몸 다섯 줄이 섞였습니다. 들여쓰기는 지웠으니 중괄호 줄로 덩어리를 가르세요. console.log(sum(3));이 6을 찍도록 처음부터 차례로 기호를 늘어놓으세요.
㉠ return total;
㉡ for (let i = 1; i <= n; i++) {
㉢ total = total + i;
㉣ let total = 0;
㉤ }
힌트
하위 목표 '합을 0으로 → 하나씩 더하기 → 끝나고 쓰기' 다음이 '돌려주기'입니다.
놓은 뒤 물음
㉠ return total;을 ㉤ 아래(반복 밖)에 두는 까닭을 고르세요.
- ① 반복 안에 두면 첫 바퀴에서 함수가 끝나 1만 돌려주기 때문
- ② 반복 안에 두면 오류로 멈추기 때문
- ③
return은 늘 함수 몸의 맨 끝 줄에만 쓸 수 있기 때문
정답
㉣ ㉡ ㉢ ㉤ ㉠ 차례이고, 까닭은 ①입니다. 다섯 줄의 차례 120가지를 모두 돌려 보면 6을 찍는 것은 이 차례 하나입니다.
- ② ㉠을 ㉢ 다음(반복 안)에 두어도 오류는 나지 않습니다. 첫 바퀴에서 1을 돌려주고 끝나 2절처럼 1이 찍힙니다.
- ③
return은 몸 어디에나 쓸 수 있습니다. 다만 만나는 순간 함수가 끝나므로(규칙 5), 합을 다 모은 뒤에 둡니다.
㉣을 ㉡ 안에 두면 바퀴마다 total이 새로 0에서 시작하고, ㉠이 읽는 반복 밖에는 total이 없어 ReferenceError로 멈춥니다.
3. 장바구니 값 3000원에 봉투 값을 더하려 합니다. 무엇이 찍힐까요? 마지막 줄까지 글자 그대로 쓰세요.
function bag(n) {
console.log(n * 100);
}
const pay = 3000 + bag(2);
console.log(pay);
힌트
5번 줄에서 bag(2)가 부른 자리에 무엇을 놓는지, 그 사이 화면에 무엇이 찍히는지 차례로 적어 봅니다.
정답
모두 2줄입니다.
200
NaN5번 줄이 bag을 부르면 2번 줄이 화면에 200을 씁니다. bag에는 return이 없어 undefined를 돌려주므로 식은 3000 + undefined가 되고, NaN으로 접힙니다. 6번 줄은 NaN을 찍습니다.
흔한 오답은 3200 한 줄입니다. 찍은 200이 부른 자리로 돌아온다고 본 것입니다(찍는 것과 돌려주는 것이 같다는 생각). 200을 더하려면 2번 줄을 return n * 100;으로 씁니다(규칙 5).
컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요.
1절 둘째 코드(여덟 줄)를 main.js에 저장해 돌립니다. 그다음 2번 줄 return 4000 * n; 아래에 console.log('계산');을 한 줄 넣으면 찍히는 줄이 달라질지 먼저 적고, 넣고 돌려서 맞춰 봅니다.
저장하고 돌리는 법은 내 컴퓨터에서 돌려 보기에 있습니다.