출처 모던 자바스크립트 Deep Dive을 보고 정리한 내용입니다.
1부터 5까지 출력하는 모든 정수를 출력하는 함수와 1부터 5까지 홀수만 출력하는 함수를 작성해보자.
function repeat() {
for(let i = 0; i < 5; i++){
console.log(i); //1 2 3 4
}
}
function repeatOdd () {
for(let i = 0; i < 5; i++){
if(i % 2 === 1){
console.log(i); //1 3
}
}
}
위 함수들은 공통적으로 작동하는 로직이 존재한다. 함수에서 변하지 않는 로직을 미리 정의하고, 경우에 따라 다르게 작동하는 로직을 추상화하여 함수 외부에서 내부로 전달해보자.
function repeat(f) {
for(let i = 0; i < 5; i++){
f(i);
}
}
var logAll = function (num) {
console.log(num);
}
var logOdd = function (num) {
if(i % 2 === 1){
console.log(i);
}
}
repeat(logAll); //1 2 3 4
repeat(logOdd) // 1 3
repeat 함수는 위 과정을 통해 더 이상 함수 내부 로직에 의존하지 않는 유연한 코드가 되었다. 이때 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백함수(Callback Function), 매개변수를 통해 함수 외부에서 콜백함수를 받은 함수를 고차함수(Higher-Order Function)이라고 한다.
콜백함수는 고차함수에 의해서 호출되며, 고차함수는 필요에 따라 콜백함수에 인수를 전달할 수 있다.
repeat(function(i) {
if(i % 2 === 1){
console.log(i);
}
});
이 때 콜백함수는 고차함수가 호출될 때마다 평가되어 함수객체를 생성한다. 그러므로 콜백함수를 여러 곳에서 사용하거나 콜백함수를 받는 고차함수가 자주 실행된다면 콜백함수를 따로 정의하는 것이 효율적이다.
또한 콜백함수는 배열 고차함수에도 사용된다.
var result = [1, 2, 3].map(function(item) {
return item * 2;
});
console.log(result); //[2, 4, 6]
var result2 = [1, 2, 3].filter(function(item) {
return item % 2;
});
console.log(result2); //[1, 3]
var result3 = [1, 2, 3].reduce(function(acc, cur) {
return acc + cur;
}, 0);
console.log(result3); //6