13.6.2 함수에 함수 전달
함수에 함수를 전달하는 예제는 setTimeout과 forEach에서 이미 봤습니다.
함수에 함수를 전달하는 다른 용도는 비동기적 프로그래밍입니다.
이런 용도로 전달하는 함수를 보통 콜백(callback)이라 부르며, 약자로 cb를 쓸 때가 많습니다.
콜백 함수는 자신을 감싼 함수가 실행을 마쳤을 때 호출됩니다.
콜백은 14장에서 자세히 설명합니다.
함수에 함수를 전달하는 대표적인 사례가 콜백이긴 하지만, 그게 전부는 아닙니다.
함수는 동작이고, 함수를 받은 함수는 그 동작을 활용할 수 있습니다.
배열에 들어있는 숫자를 모두 더하는 단순한 함수 sum이 필요하다고 합시다(배열에 숫자가 아닌 것이 들어있을 때를 대비한 체크나 에러 처리는 생략하겠습니다).
그런 함수는 쉽게 만들 수 있습니다.
그런데 숫자의 제곱(square) 을 합해서 반환하는 함수가 필요하다면?
물론 새 함수 sumOfSquares를 만들어도 됩니다.
그런데, 세제곱을 합해서 반환하는 함수도 필요하다면?
이런 상황에서 함수에 함수를 전달한다는 발상이 필요합니다.
sum을 이렇게 만들었다고 합시다.
function sum(arr, f) {
// 함수가 전달되지 않았으면 매개변수를 그대로 반환하는 null 함수를 씁니다.
if (typeof f != 'function') f = x => x;
return arr.reduce((a, x) => a += f(x), 0);
}
sum([1, 2, 3]); // 6
sum([1, 2, 3], x => x*x); // 14
sum([1, 2, 3], x => Math.pow(x, 3)); // 36
임의의 함수를 sum에 전달하면 원하는 일을 거의 모두 할 수 있습니다.
제곱근의 합이 필요한가요?
아무 문제도 없습니다.
숫자의 4.233 제곱의 합이 필요한가요?
바로 할 수 있습니다.
sum을 바로, 즉 함수를 넘기지 않고 호출해야 할 수도 있습니다.
함수를 넘기지 않고 sum을 호출하면 매개변수 f의 값은 undefined이므로 에러가 일어납니다.
에러를 방지하기 위해 함수가 아닌 것은 모두 ‘null 함수’, 즉 아무 일도 하지 않는 것으로 바꿉니다.
즉 null 함수 f에 5를 넘기면 그대로 5를 반환합니다.
배열의 모든 요소에서 null 함수를 호출하는 것보다는 요소를 그냥 더하는 함수를 한 번 호출하는 등 더 효율적인 방법이 물론 있겠지만, 이런 식으로 ‘안전한’ 함수를 만들 수 있다는 걸 충분히 이해했을 겁니다.