JavaScript · 2장 기본
함수를 값처럼: 함수 표현식 · 콜백 · 화살표 함수
자바스크립트에서 함수는 숫자나 문자열처럼 변수에 담고, 다른 함수에 건네줄 수 있는 값이에요. 이 성질 덕분에 "버튼을 누르면 이 함수를 불러 줘", "배열의 항목마다 이 함수를 적용해 줘" 같은 코드를 쓸 수 있어요.
01. 함수도 값이에요: 함수 표현식
앞 글의 function 이름() {}은 함수 선언문이에요. 함수를 만들어 변수에 담는 함수 표현식도 있어요. 담긴 변수 이름으로 부르는 방법은 똑같아요.
const vat = function (price) {
return price * 0.1;
};
console.log(vat(20000)); // 2000
console.log(typeof vat); // function
const tax = vat; // 다른 이름에 그대로 담을 수도 있어요
console.log(tax(5000)); // 500
둘의 차이는 언제부터 부를 수 있느냐예요. 함수 선언문은 엔진이 코드를 실행하기 전에 미리 준비해 둬서, 선언한 줄보다 위에서도 부를 수 있어요(호이스팅). 함수 표현식은 const 변수이니 그 줄을 지난 뒤에만 쓸 수 있어요.
console.log(greet('하늘')); // 안녕, 하늘 — 선언문은 위에서도 돼요
function greet(name) {
return '안녕, ' + name;
}
console.log(shout('바다')); // 표현식은 안 돼요
const shout = function (name) {
return name + '!!';
};
02. 함수를 건네주는 콜백
함수가 값이니 다른 함수의 인자로 넣을 수 있어요. 이렇게 건네져서 나중에 불리는 함수를 콜백(callback, 다시 불러 줄 함수)이라고 해요. 받는 쪽은 "무엇을 할지"를 몰라도 "언제 할지"만 정하면 되니, 하나의 함수를 여러 용도로 쓸 수 있어요.
function repeat(times, action) {
for (let i = 1; i <= times; i++) {
action(i); // 건네받은 함수를 불러요
}
}
function sayHi(n) {
console.log(`${n}번째 안녕`);
}
repeat(3, sayHi); // sayHi를 부르지 않고 그대로 건네요
콜백은 자바스크립트 어디에나 있어요. 정해진 시간 뒤에 부르는 setTimeout, 배열의 항목마다 부르는 map · filter(5장), 버튼을 누를 때 부르는 이벤트 리스너(2부)가 모두 콜백을 받아요.
setTimeout(function () {
console.log('0.1초 뒤에 불렸어요');
}, 100);
console.log('먼저 실행돼요');
03. 화살표 함수
콜백처럼 짧은 함수를 자주 쓰다 보니 더 짧은 문법이 생겼어요. function 대신 =>를 쓰는 화살표 함수예요.
- 매개변수가 하나면 괄호를 뺄 수 있어요:
n => n * 2 - 본문이 식 하나면 중괄호와
return을 뺄 수 있어요. 그 식의 값이 돌아가요. - 본문이 여러 줄이면 중괄호를 쓰고, 이때는
return을 직접 써야 해요.
const double = n => n * 2;
const add = (a, b) => a + b;
const shipping = amount => {
if (amount >= 50000) return 0;
return 3000;
};
console.log(double(4), add(2, 3), shipping(42000)); // 8 5 3000
setTimeout(() => console.log('화살표 콜백'), 0);
함정이 하나 있어요. 객체를 바로 돌려주려고 => { name: … }라고 쓰면, 엔진은 중괄호를 객체가 아니라 함수 본문으로 읽어요. 그래서 undefined가 나와요. 객체를 돌려줄 땐 괄호로 감싸요.
const makeItem = name => ({ name, qty: 1 });
const broken = name => { name: name };
console.log(makeItem('연필')); // { name: '연필', qty: 1 }
console.log(broken('연필')); // undefined
화살표 함수에는 자기만의 this가 없다는 차이도 있어요. 객체의 메서드를 만들 때 이 차이가 중요해지는데, 4장과 6장에서 다뤄요.
"안녕!"이 0.1초 뒤에 나오게 하려고 했는데, 바로 나와 버려요. 출력 순서가 기다리는 중 → 안녕!이 되게 한 곳만 고쳐 보세요.
function hello() {
console.log('안녕!');
}
setTimeout(hello(), 100);
console.log('기다리는 중');
해답 보기
hello()는 함수를 그 자리에서 불러서 그 결과(undefined)를 setTimeout에 넘겨요. 함수 자체를 건네려면 괄호를 빼요.
setTimeout(hello, 100);
인자를 넣어 불러야 한다면 setTimeout(() => hello('하늘'), 100)처럼 화살표 함수로 감싸서 건네요.
04. 실전 포인트
- 언제 쓰나요? 콜백과 짧은 계산은 화살표 함수가 기본이에요(
prices.map(p => p * 2)). 파일의 주요 함수처럼 이름이 중요하고 여러 곳에서 부르는 함수는 함수 선언문이나const+ 화살표 함수 중 팀 규칙을 따라요. - 대신 쓰는 것: 객체의 메서드에는 화살표 함수를 쓰지 않아요(
this문제, 4장). 콜백이 길어지면 이름 있는 함수로 빼서 건네요. 읽기도 쉽고 오류 메시지에 이름이 나와 디버깅도 쉬워요. - 흔한 실수: 콜백 자리에
hello()처럼 괄호를 붙여 바로 불러 버리는 것, 중괄호 본문에서return을 빼먹는 것, 객체를 돌려주며 괄호를 빼먹는 것이에요.
정리
- 함수는 값이라 변수에 담고(함수 표현식) 인자로 건넬 수 있어요. 선언문은 위에서도, 표현식은 그 줄 뒤에서만 불러요.
- 건네져서 나중에 불리는 함수가 콜백이에요. 건넬 땐 괄호 없이 함수 자체를 넘겨요.
- 화살표 함수
(a, b) => a + b는 식 하나면 그 값을 돌려주고, 중괄호 본문이면return을 직접 써요. - 객체를 바로 돌려줄 땐
() => ({ … })처럼 괄호로 감싸요.