1. 일급 객체
- JS 에는 특별한 대우를 받는 일급 객체( First-class citizen )가 있다.
- 대표적인 일급 객체 중 하나가 함수이다.
-----------------------------------------------------------------------------------
2. 함수의 특별 취급
- 변수에 할당할 수 있다.
- 다른 함수의 인자로 전달될 수 있다.
- 다른 함수의 결과로서 리턴될 수 있다.
-----------------------------------------------------------------------------------
3. 고차 함수
- 고차 함수( higher order function )는 함수를 인자로 받을 수 있고, 함수의 형태로 리턴할 수 있는 함수이다.
- 함수는, 함수를 담은 변수를 인자로 전달받을 수 있다.
- 함수 내부에서 변수에 함수를 할당할 수 있다.
- 어떤 고차 함수에 함수를 인자로 전달하고, 고차 함수는 함수 자체를 리턴한다.
- 이때 다른 함수의 인자로 전달되는 함수를 콜백 함수( callback function )라고 한다.
** '함수를 리턴하는 함수'를 고안해 낸 논리학자 하스켈 커리의 이름을 따서 '커리 함수'라고 한다. '커리 함수'라는 용어를 사용하는 경우에는 고차 함수 용어를 '함수를 인자로 받는 함수'에만 한정해 사용하기도 하지만, 고차함수가 커리함수를 포함한다. 그래서 '함수를 리턴하는 함수'와 '함수를 인자로 받는 함수' 모두 고차함수로 부른다.
3 - 1) 다른 함수를 인자로 받는 경우
function double(num) {
return num * 2;
}
function doubleNum(func, num) {
return func(num);
}
let output = doubleNum(double, 4);
console.log(output);
// -> 8
// 함수 doubleNum 은 다른 함수를 인자로 받는 고차 함수이다.
// 함수 doubleNum 의 첫 번째 인자 func 에 함수가 들어올 경우 함수 func 는 함수 doubleNum 의 콜백 함수이다.
3 - 2) 함수를 리턴하는 경우
function adder(added) {
return function (num) {
return num + added;
};
}
// 함수 adder 는 다른 함수를 리턴하는 고차 함수이다.
// adder 는 인자 한 개를 입력받아서 익명 함수를 리턴한다.
// 리턴되는 익명 함수는 인자 한 개를 받아서 added 와 더한 값을 리턴한다.
let output = adder(5)(3); // -> 8
// adder 가 리턴하는 함수를 변수에 저장할 수 있다.
// JS 에서 함수는 일급 객체이기 때문이다.
const add3 = adder(3);
output = add3(2);
console.log(output); // -> 5
3 - 3) 함수를 인자로 받고, 함수를 리턴하는 경우
function double(num) {
return num * 2;
}
function doubleAdder(added, func) {
const doubled = func(added);
return function(num) {
return num + doubled;
};
}
// 함수 doubleAdder 는 고차함수이다.
// 함수 doubleAdder 의 인자 func 는 함수 doubleAdder 의 콜백 함수이다.
// 함수 double 은 함수 doubleAdder 의 콜백으로 전달되었다.
doubleAdder(5, double)(3); // -> 13
// doubleAdder 가 리턴하는 함수를 변수에 저장할 수 있다. ( 일급 객체 )
const addTwice3 = doubleAdder(3, double);
addTwice(2); // -> 8
-----------------------------------------------------------------------------------
4. 내장 고차함수
- JS 에는 기본적으로 내장된 고차함수가 여럿 있다. 그중에서 배열 메소드들 중 일부가 대표적인 고차함수가 해당된다.
4 - 1) 배열의 filter 메소드
- 모든 배열의 요소 중에서 특정 조건을 만족하는 요소를 걸러낸다.
const isEven = function (num) {
return num % 2 === 0;
};
let arr = [1, 2, 3, 4];
let output = arr.filter(isEven);
console.log(output); // ->> [2, 4];
const isLteFive = function (str) {
return str.lenght <= 5;
};
arr = ['hello', 'code', 'states', 'happy', 'hacking'];
output = arr.filter(isLteFive);
console.log(output); // ->> ['hello', 'code', 'happy'];
// 걸러내는 기준이 되는 특정 조건이 filter 메소드의 인자로 전달되고 이 때 인자는 함수의 형태이다.
// 걸러내기 위한 조건을 명시한 함수를 인자로 받기 때문에 고차함수이다.
4 - 2) 배열의 map 메소드
- map 은 모든 요소에 동일한 값을 주어 결과값을 return 한다.
- 행동은 사용자가 직접 작성하여 함수를 작성해서 작용한다.
- 기존 배열을 수정하지 않는다.
const cartoons = [
{
id: 1,
bookType: 'cartoon',
title: '식객',
subtitle: '어머니의 쌀',
createdAt: '2003-09-09',
},
{
id: 2,
... 생략
}
];
const findSubtitle = function(cartoon) {
return cartoon.subtitle;
}; // 만화책 한 권의 제목을 리턴하는 함수
const subtitles = cartoons.map(findSubtitle);
4 - 3) 배열의 reduce 메소드
- reduce 는 배열을 하나의 값으로 만들어준다.
- reduce 는 초기값을 정할 수 있고 정하지 않으면 배열의 첫 번째 요소가 초기값이 된다.
- 초기값부터 시작하여 우리가 원하는 함수 로직으로 값이 누적되어 결과값으로 나오게된다.
const cartoons = [
{
id: 1,
bookType: 'cartoon',
title: '식객',
subtitle: '어머니의 쌀',
createdAt: '2003-09-09',
averageScore: 9.66
},
{
id: 2,
... 생략
}
];
const scoreReducer = function (sum, cartoon) {
return sum + cartoon.averageScore;
}; // 단행본 한 권의 평점을 누적값에 더한다.
let initialValue = 0;
const cartoonsAvgScore = cartoons.reduce(scoreReducer, initialValue) / cartoons.length;
// 모든 책의 평점을 누적한 평균을 구한다.
1) reduce 사용법 - 배열을 문자열로
function joinName (resultStr, user) {
resultStr = resultStr + user.name + ', ';
return resultStr;
};
let users = [
{ name: 'Tim', age: 40 },
{ name: 'Satya', age: 30 },
{ name: 'Sundar', age: 50 },
];
users.reduce(joinName, '');
2) reduce 사용법 - 배열을 객체로
function makeAddressBook(addressBook, user) {
let firstLetter = user.name[0];
if(firstLetter in addressBook) {
addressBook[firstLetter].push(user);
} else {
addressBook[firstLetter] = [];
addressBook[firstLetter].push(user);
}
return addressBook;
}
let users = [
{ name: 'Tim', age: 40 },
{ name: 'Satya', age: 30 },
{ name: 'Sundar', age: 50 }
];
users.reduce(makeAddressBook, {});
** 사실 reduce 메소드를 잘 이용하면 매우 많은 곳에 사용할 수 있었다. 오늘 여러 알고리즘 문제들을 풀면서 느꼈다.. 좀 더 쓰면서 더 익숙해져야 할듯 하다.
-----------------------------------------------------------------------------------
5. 왜 고차함수를 써야할까?
- 추상화 : 추상화는 복잡한 어떤 것을 압축해서 핵심만 추출한 상태로 만드는 것이다.
- 추상화는 곧 생산성의 향상이다.
- 추상화의 관점에서 함수를 바라보면, 함수는 사고 또는 논리의 묶음이다.
- 함수를 통해 얻은 추상화를, 한 단계 더 높인 것이 고차함수이다.
'Java Script' 카테고리의 다른 글
JS - 재귀 (0) | 2021.05.12 |
---|---|
JS - 객체 지향 (0) | 2021.05.10 |
JS - DOM (0) | 2021.04.26 |
JS - Spread / Rest 문법 (0) | 2021.04.23 |
JS - 클로저 (0) | 2021.04.22 |