화살표 함수(arrow function)는 (n) => n * 2처럼 function 낱말 없이 짧게 쓰는 함수입니다. 함수도 수·문자열처럼 값이라, 화살표 함수에 const로 이름을 붙이고 그 함수에 이름을 하나 더 붙이거나 다른 함수에 넘길 수 있습니다.
한 줄로 끝나는 계산을 함수로 만들 때마다 function·return·중괄호를 다 쓰면 코드가 길어집니다. 다음 레슨에서 함수를 다른 함수에 넘길 때도 이 짧은 꼴을 자주 씁니다.
이 레슨에서는 화살표 함수를 쓰는 법과 함수가 값이라는 것, 그리고 function 선언과 const 함수가 언제 만들어지는지 봅니다.
1화살표 함수 쓰는 법
화살표 함수는 괄호 안에 매개변수를 쓰고, => 뒤에 돌려줄 식을 씁니다.
const double = (n) => n * 2;
const add = (a, b) => a + b;
console.log(double(4));
console.log(add(1, 2));
8
31번 줄의 (n) => n * 2는 몸이 return n * 2;인 function double(n) 함수와 같은 일을 합니다. => 뒤가 식 하나면 return을 쓰지 않아도 그 식의 값을 돌려줍니다.
만든 함수에는 const로 이름을 붙이고, 부를 때는 다른 함수처럼 이름 뒤에 괄호를 붙입니다. 매개변수가 둘이면 2번 줄처럼 쉼표로 나눕니다.
이 과목은 매개변수가 하나여도 괄호를 씁니다. 다른 자료에서 n => n * 2처럼 괄호 없는 꼴을 만나면 같은 함수입니다.
몸이 여러 줄이면 중괄호로 감쌉니다. 아래 a와 b는 무엇을 돌려줄까요? 답을 정한 뒤 펼쳐 보세요.
const a = (n) => {
n * 2;
};
const b = (n) => {
return n * 2;
};
console.log(a(4), b(4));
실행 결과 보기
undefined 8예상과 다르면 그곳이 배울 곳입니다.
중괄호를 쓰면 몸이 덩어리가 되어 function으로 만든 함수와 같은 규칙을 따릅니다. a의 몸은 8을 계산하고 그대로 버려, return이 없는 함수처럼 undefined를 돌려줍니다. b는 return이 있어 8을 돌려줍니다(규칙 5).
8 8을 예상했다면, 중괄호 안의 마지막 식도 저절로 돌려준다고 본 것입니다.
2함수도 값이다
그림의 첫 장면 코드입니다.
const double = (n) => n * 2;
const calc = double;
console.log(calc(4));
81번 줄은 화살표 함수를 만들어 이름 double을 붙입니다. 2번 줄의 double에는 괄호가 없어 함수를 부르지 않습니다. 오른쪽 double이 가리키는 함수에 이름 calc를 하나 더 붙일 뿐입니다. 함수는 하나이고 이름표가 둘입니다(규칙 3).
그래서 3번 줄의 calc(4)는 double과 같은 함수를 불러 8을 찍습니다. console.log(calc)로 찍어 보면 [Function: double]이 찍힙니다. calc가 가리키는 것이 처음 double이라는 이름으로 만든 그 함수이기 때문입니다.
수에 이름을 둘 붙인 이름표 다시 붙이기와 const의 let b = a;와 같은 규칙입니다. 함수도 이름이 가리키는 값이라, 이름을 붙이고 넘길 수 있습니다.
3function 선언은 먼저, const 함수는 그 줄에서 만들어진다
그림의 둘째 장면 코드입니다. 함수를 만드는 줄보다 부르는 줄이 위에 있습니다.
console.log(double(4));
const double = (n) => n * 2;
main.js:1console.log(double(4)); ^ ReferenceError: Cannot access 'double' before initialization at main.js:1:13ReferenceError 줄의 설명은 '초기화하기 전에는 double을 쓸 수 없다', 곧 double이 아직 값에 붙지 않았다는 뜻입니다. const 이름은 파일 처음부터 있지만, 그 줄을 실행해 값에 붙기 전에는 쓸 수 없습니다. 그림은 이 이름을 '아직 못 씀'으로 그립니다. 자료에 따라 이 구간을 일시적 사각지대(TDZ)라고도 부릅니다.
같은 자리에 function 선언을 두면 다릅니다.
console.log(double(4));
function double(n) {
return n * 2;
}
8함수 만들고 부르기에서 본 것처럼 function 선언은 파일을 실행하기 전에 먼저 만들어집니다. 그래서 위에서 불러도 됩니다. 함수 선언을 파일 맨 위로 끌어올린 것처럼 보여 이를 끌어올림이라 하고, 자료에 따라 호이스팅(hoisting)이라고도 부릅니다.
실행은 그대로 위에서 아래로 한 줄씩입니다(규칙 1). const 함수는 만드는 줄 아래에서 부르면 어디서나 됩니다.
예제
계산을 작은 함수로 나누기
할인 계산은 식 하나라 중괄호 없이, 금액 계산은 줄이 둘이라 중괄호와 return으로 썼습니다.
const sale = (won) => won - 500;
const pay = (won, qty) => {
const sum = won * qty;
return sale(sum);
};
console.log(pay(4000, 2));
75004번 줄은 sale을 불러 돌려받은 7500을 다시 돌려줍니다. 화살표 함수도 부르면 새 칸이 생겨, pay 칸의 won과 sale 칸의 won은 따로 있는 이름입니다(규칙 5).
자주 틀리는 곳
틀린 생각: 화살표 함수는 중괄호로 감싸도 식의 값을 돌려준다.
=> 뒤의 식이 저절로 돌아오는 것을 보았으니, 중괄호 안의 식도 그럴 것 같습니다. 1절 맞혀 보기의 a처럼 중괄호 몸은 return 없이 undefined를 돌려줍니다.
맞는 규칙: => 뒤가 식 하나면 그 값을 돌려주고, 중괄호를 쓰면 몸이 덩어리라 return이 있어야 값을 돌려줍니다(규칙 5).
틀린 생각: const로 만든 함수도 function 선언처럼 위에서 부를 수 있다.
둘 다 함수를 만드는 줄이니 같게 움직일 것 같습니다. 3절처럼 const 함수는 그 줄이 실행되기 전에 부르면 멈춥니다.
맞는 규칙: 실행 전에 먼저 만들어지는 것은 function 선언뿐입니다. const로 만든 함수는 그 줄 아래에서 부릅니다(규칙 1).
틀린 생각: 함수에 다른 이름을 붙이면 함수가 하나 더 생긴다.
이름이 새로 생기니 함수도 새로 하나 생길 것 같습니다. 2절의 calc처럼 새 이름표가 같은 함수를 가리킬 뿐이고, 함수는 하나입니다.
맞는 규칙: 함수도 값이라 이름을 붙이면 그 함수에 이름표가 하나 늘 뿐입니다. 괄호를 붙이지 않으면 부르지도 않습니다(규칙 3).
확인 문제
1. 예제 코드의 6번 줄을 console.log(pay(4000, 3));으로 바꿨습니다. 무엇이 찍힐까요?
const sale = (won) => won - 500;
const pay = (won, qty) => {
const sum = won * qty;
return sale(sum);
};
console.log(pay(4000, 3));
힌트
6번 줄에서 pay를 부르면 3번 줄이 sum을 무엇에 붙이는지, 그다음 4번 줄이 sale에 무엇을 넘기는지 차례로 적습니다.
정답
115003번 줄이 sum을 12000에 붙이고, 4번 줄이 sale을 불러 12000 - 500을 계산한 11500을 돌려받아 그대로 돌려줍니다.
흔한 오답은 12000입니다. 4번 줄에서 sale을 부르지 않고 sum을 돌려준다고 본 것입니다. return sale(sum);은 sale을 먼저 불러 돌려받은 값을 돌려줍니다(규칙 5). 10500이라고 썼다면 할인을 잔마다 뺀 것입니다 — sale은 합계 sum에 한 번 불립니다.
2. 잔 수를 받아 커피 값을 돌려주는 함수를 화살표 함수로 쓰려 합니다. 2번 줄이 12000을 찍도록 빈칸을 채우세요.
const price = ____;
console.log(price(3));
힌트
(매개변수) => 식 꼴입니다. 잔 수에 4000을 곱합니다.
정답
(n) => n * 4000입니다. 매개변수 이름은 cups처럼 다른 이름이어도 됩니다.
흔한 오답은 (n) => { n * 4000 }처럼 중괄호로 감싸는 것입니다. 중괄호 몸에 return이 없어 undefined가 찍힙니다. 중괄호를 쓰려면 (n) => { return n * 4000; }으로 씁니다(규칙 5).
3. 걸음 수를 다루는 함수 둘을 파일 아래쪽에 만들었습니다. 무엇이 찍힐까요? 오류가 난다고 보면 찍히는 줄 다음에 오류 이름을 쓰세요.
console.log(km(3000));
console.log(steps(2));
function km(n) {
return n / 1000;
}
const steps = (k) => k * 1300;
힌트
1번 줄과 2번 줄을 실행하는 때에 km과 steps가 이미 함수에 붙어 있는지 따로 봅니다.
정답
3을 찍은 뒤 2번 줄에서 ReferenceError로 멈춥니다.
3main.js:2console.log(steps(2)); ^ ReferenceError: Cannot access 'steps' before initialization at main.js:2:13km은 function 선언이라 실행 전에 만들어져 1번 줄에서 불러도 3을 돌려줍니다. steps는 const 이름이라 7번 줄을 실행하기 전에는 아직 쓸 수 없어, 2번 줄에서 멈춥니다.
흔한 오답은 3과 2600 두 줄입니다. const 함수도 function 선언처럼 먼저 만들어진다고 본 것입니다. 첫 줄부터 ReferenceError라고 쓴 답은 function 선언도 그 줄에 와야 만들어진다고 본 것입니다(규칙 1).
컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요.
2절 코드(세 줄)를 main.js에 저장해 돌립니다. 그다음 1번 줄의 몸을 중괄호로 감싸 (n) => { n * 2 }로 바꾸면 3번 줄이 무엇을 찍을지 먼저 적고 돌려 봅니다. 이어서 중괄호 안에 return을 넣어 다시 돌려 봅니다.
저장하고 돌리는 법은 내 컴퓨터에서 돌려 보기에 있습니다.