함수를 인자로 받거나 함수를 반환하는 함수
function processArray(arr, callback) {
for (var i = 0; i < arr.length; i++) {
callback(arr[i]);
}
}
function printElement(el) {
console.log(el);
}
var numbers = [1, 2, 3, 4, 5];
processArray(numbers, printElement);
// 출력:
// 1
// 2
// 3
// 4
// 5
자바스크립트에서 함수는 일급 객체
이기 때문에 매개변수처럼 사용할 수 있다.
function add(a) {
return function(b) {
return a + b;
};
}
var add5 = add(5);
console.log(add5(3)); // 출력: 8
// 함수 합성 예시
function multiplyBy2(x) {
return x * 2;
}
function add1(x) {
return x + 1;
}
var composedFunction = function(x) {
return add1(multiplyBy2(x));
};
console.log(composedFunction(3)); // 출력: 7
앞서 살펴본 고차함수를 잘 이용하면 코드가 더 간단하고 명료해진다. 고차 함수는 다른 함수를 인자로 받거나 그 결과로 함수를 반환하는 함수이다. 배열의 표준 정렬 메서드 sort()
를 생각해보자
function compareNumbers(x,y){
if( x < y ){
return -1;
}
if(x > y ){
return 1;
}
return 0;
}
[3,2,1,4,6,5].sort(compareNumbers); // [1,2,3,4,5,6]
호출자로 부터(여기서는 배열) 비교 메서드를 가지는 객체를 전달받기를 요구하지만, 하나의 메서드만 필요하기 때문에 함수를 직접 받는것이 더 간결하다.
이 예제는 익명함수를 통해 더 간단하게 만들 수 있다.
[3,2,1,4,6,5].sort(function(x,y)=>{
if( x < y ){
return -1;
}
if(x > y ){
return 1;
}
return 0;
}); // [1,2,3,4,5,6]
고차 함수를 사용하면 이처럼 코드를 간결하게 만들 수 있다.
일반적인 반복문으로 작성한 코드는 다음과 같다.
var name = ["Fred","Wilma","Pebbles"];
var upper = [];
for(var i = 0 ; i <name.length;i<++){
upper[i] = names[i].toUpperCase();
}
upper; // ["FRED","WILMA","PEBBLES"]
map()
메서드를 사용한 코드
var name = ["Fred","Wilma","Pebbles"];
var upper = name.map(function(name){
return name.toUpperCase();
})
upper; // ["FRED","WILMA","PEBBLES"]
반복문의 세부 사항을 완전히 제거하고 각요소의 변환을 지역함수내에서 구현만 하면 된다!
고차 함수의 사용에 익숙해지고 나면, 직접 작성할 기회도 생길 것이다. 비슷하거나 중복된 코드를 자주 보게 된다면 이는 숨길 수 없는 고차함수 추상의 신호이다.
var aIndex = "a".charCodeAt(0); //97
var alphabet = "";
for(var i = 0;i<26;i++){
alpabet += String.fromCharCode(aIndex+i);
}
alphabet; // abcdefghijklmnopqrstuvwxyz
var digits = "";
for(var i = 0;i<10;i++){
digits += i; //문자열에 숫자를 더하면 문자가 됨
}
digits // "0123456789"
var random = "";
for(var i = 0;i<8;i++){
random += String.fromCharCode(Math.floor(Math.random()*26)+aIndex);
}
random; //"enslxifh" (매번 다른결과 반환)
이 예제들은 서로다른 문자열을 반환하지만 공통된 로직
을 소유하고 있다. 이제 공통 부분을 추출하고 유틸리티 함수로 옮기면 다음과 같은 코드를 만들 수 있다.
//추상화된 고차함수
function buildString(n, callback){
var result ="";
for(var i = 0;i<n;i++){
result += callback(i);
}
해당 공통로직을 사용하면 이전의 세 예제를 다음과 같이 간단하게 구현할 수 있다.
var alphabet = buildString(26, function(i){
return String.fromCharCode(aIndex+i);
})
alphabet; // abcdefghijklmnopqrstuvwxyz
var disits = buildString(10, function(i){
return i;
})
digits // "0123456789"
var random = builderString(8, function(){
return String.fromCharCode(Math.floor(Math.random()*26+aIndex));
})
random; //"enslxifh" (매번 다른결과 반환)
고차함수추상을 생성하는 방식은 장점이 많다.