자바스크립트에는 특별한 대우를 받는 일급 객체(first-class citizen)
가 존재한다. 일급 객체
란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리키며 대표적인 일급 객체
가 바로 함수
이다. 따라서 함수는 다음과 같은 조건을 만족한다.
고차 함수(higher order function)
는 함수가 일급 객체
의 조건을 만족하기 때문에 실현 가능한 함수로, 함수를 인자(argument)로 받을 수 있고, 함수의 형태로 리턴할 수 있는 함수를 말한다.
이 경우 다른 함수에 인자로 전달되는 함수를 '콜백(callback) 함수'라고 하며, 함수를 리턴하는 함수의 경우 '커리 함수'라고 부른다. 각각의 예시는 아래와 같다.
function addTwo(num) {
return num + 2;
}
function addNum(func, num) {
return func(num);
}
let output = addNum(addTwo, 4);
console.log(output); // 6
예시에서 addNum은 다른 함수를 인자로 받는 고차 함수이다. 이러한 addNum의 인자 func가 바로 콜백 함수로, 위와 같이 addTwo를 인자로 받으면 이 또한 addNum의 콜백 함수이다.
function adder(added) {
return function (num) {
return num + added;
};
}
let output = adder(3)(4);
console.log(output); // 7
const add5 = adder(5);
output = add5(2);
console.log(output); // 7
위 예시의 경우, adder는 다른 함수를 리턴하는 고차 함수이다. adder는 인자 num을 입력받아서 익명 함수를 리턴하고, 리턴되는 익명 함수는 인자를 added와 더한 값을 리턴한다. 여기서 중요한 점은 adder()은 함수이므로 다시 호출 연산자()를 붙일 수 있다는 점이다. 이러한 특징 덕분에 adder(3)(4)과 같은 형태가 가능한 것이다. 또한 예시의 adder(5)와 같이 adder가 리턴하는 함수는 다시 변수에 할당될 수 있다. 이러한 모든 과정이 가능한 이유는 바로 함수가 '일급 객체'이기 때문이다.
그렇다면 이러한 고차함수를 사용하는 이유는 무엇일까? 기본적으로 자바스크립트가 함수형 프로그래밍을 지향하며, 이러한 함수형 프로그래밍이 불변성(Immutability)을 원칙으로 하기 때문이다. 함수형 프로그래밍은 순수 함수(Pure function)와 보조 함수(sub function)의 조합만을 사용하고, 변수의 사용을 억제하여 안정성을 높이려는 프로그래밍 패러다임이다. 이러한 함수형 프로그래밍은 조건문과 반복문의 사용 없이 불변성을 가진 함수로 모든 것을 표현하기 때문에 고차함수의 사용은 필수적이다.
고차함수를 이용하는 또 다른 이유는 바로 '추상화'이다. 추상화(abstraction)란 복잡한 자료, 모듈, 시스템 등으로부터 핵심적인 개념 또는 기능을 간추려 내는 것을 말한다. 예를 들어서 다음과 같이 배열의 평균을 계산하는 함수가 있다고 가정하자.
function getAverage(arr) {
let sum = 0;
for (let i = 0; i < arr.length; i++) {
sum = sum + arr[i];
}
return sum / arr.length;
}
let output = getAverage([1, 2, 3]);
console.log(output); // --> 2
이러한 함수는 한 번만 정의하면 매번 새로운 for 반복문을 작성할 필요 없이 바로 다른 배열에도 사용할 수 있으며, 이름에서 그 기능을 쉽게 유추할 수 있다. 그렇기에 고차함수를 통해 높은 추상화를 구현하면 코드를 읽는 사람의 가독성도 높아진다. 나아가 추상화는 복잡한 기능을 숨겨 문제를 더욱 쉽게 해결하는 생산성 향상에도 기여한다.
추가 예정입니다.
참고
poiemaweb.com - 배열 고차 함수
MDN - First-class Function
Alex Nault - Functional Programming with JavaScript in 3 Steps