본문으로 건너뛰기

돌려받은 값 쓰기

자바스크립트 목차함수레슨 28 / 76

목차

함수가 return으로 돌려준 값은 함수를 부른 자리에 놓입니다. 그 값에 이름을 붙이거나 식과 다른 함수의 인자로 쓸 수 있고, return을 만나면 함수는 그 자리에서 끝납니다.

console.log로 찍기만 하는 함수는 결과를 화면에 보여 줄 뿐이라, 그 결과로 다시 계산할 수 없습니다. 값을 돌려받아야 합계에 더하고 다른 함수에 넘길 수 있습니다. 이 레슨에서는 돌려받은 값이 식 안에서 어떻게 쓰이는지와, return이 함수를 언제 끝내는지 봅니다.

5단계 중 1단계. 함수 price를 만들고, 부른 결과로 식을 계산하는 코드입니다. price는 처음부터 함수에 붙어 있습니다.

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:18

latte는 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);
실행 결과
7500

9번 줄과 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줄입니다.

실행 결과
12000

price(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
NaN

5번 줄이 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('계산');을 한 줄 넣으면 찍히는 줄이 달라질지 먼저 적고, 넣고 돌려서 맞춰 봅니다. 저장하고 돌리는 법은 내 컴퓨터에서 돌려 보기에 있습니다.

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

자바스크립트 목차로