- 일급 객체(first-class citizen)의 세 가지 특징을 설명할 수 있다.
- 고차 함수(higher-order function)에 대해 설명할 수 있다.
- 추상화(abstraction)에 대해 설명할 수 있다.
- 추상화의 관점에서 고차 함수가 갖는 이점에 대해 설명할 수 있다.
- 배열 메소드를 자연스럽게 사용할 수 있다.
- 고차 함수를 활용하여 프로그램을 작성할 수 있다.
자바스크립트에서 함수는 특별하게 취급한다.
고차 함수는 함수를 인자(argument)로 받거나 함수를 리턴하는 함수를 말한다. 이 때 다른 함수(caller)의 인자(argument)로 전달되는 함수를 콜백 함수(callback function)라고 한다.
콜백 함수를 전달받은 함수는 이 콜백 함수를 호출(invoke)할 수 있다. caller는 조건에 따라 콜백 함수의 실행 여부를 결정할 수 있고, 여러번 실행도 가능하다.
// 다른 함수를 인자로 받는 경우
function plusTwo(num){
return num + 2;
}
function doubleNum(func, num){
let doubleArr = [];
return func(num);
}
// 함수 doubleNum은 다른 함수(func)를 인자로 받는 고차 함수다.
// 함수 doubleNum의 첫 번째 인자 func에 함수가 들어올 경우에,
// func는 doubleNum의 콜백 함수이다.
한편, '함수를 리턴하는 함수'만을 일컫는 용어가 따로 존재한다. 이 함수를 고안해 낸 논리학자 하스켈 커리(Haskell Curry)의 이름을 따라 커리 함수라고 한다. 따로 커리 함수라는 용어를 사용하는 경우, 고차 함수란 용어를 '함수를 인자로 받는 함수'에만 한정지어서 사용하기도 한다.
// 함수를 리턴하는 경우
function adder(added){
return function (num) {
return num + added;
};
}
// 함수 adder는 다른 함수를 리턴하는 고차 함수다.
// adder는 인자 한 개(added)를 입력받아서 익명 함수를 리턴한다.
// 리턴되는 익명 함수는 인자 한 개를 받아서 added와 더한 값을 리턴한다.
함수를 인자로 받고, 함수를 리턴할 수도 있다.
배열의 요소 중에서 특정 조건을 만족하는 요소들만을 걸러내는(filter) 메소드이다. 여기서 걸러내는 기준이 되는 특정 조건은 함수 형태로 filter 메소드의 인자로 전달되어야 한다. filter 메소드는 (걸러내기 위한 조건을 명시한) 함수를 인자로 취하기 때문에 고차 함수이다. filter 메소드는 인자로 전달되는 콜백 함수에 배열의 요소를 다시 전달한다. 콜백 함수는 전달받은 배열의 요소를 받아 (조건에 따라) 참(true), 거짓(false)을 리턴해야 한다.
// 배열과 임의의 값(discarder)을 입력받아
// 기존 배열에서 discarder와 일치하는 요소가 제거된 새로운 배열 리턴
fuction removeElement(arr, discarder){
return arr.filter(function(el){
if(el !== discarder){
return true;
}
return false;
});
}
// 오피스 아워 추가 설명 부분
const arr = [1,2,3,4,5] // 3과 똑같은 것만 남기도록 하고 싶은 경우
function equalThree(element){
return element === 3;
}; // true를 리턴하는 함수
arr.filter(equalThree)// [3]
// 여기서 주의할 것은 filter는 boolean값을 반드시 리턴해야 한다는 점!
// 그리고 그 중에서 true만 리턴한다
가)
const isEven = function(element){
return element % 2 === 0
}
arr.filter(isEven) // [2,4]
나)
let result = [];
for(let i = 0; i < arr.length; i++){
if(arr[i] % 2 === 0){
result.push(arr[i])
}
}
result // [2,4]
// 가)와 나)는 동일한데 나)를 추상화 한 것이 필터, 가)이다.
배열의 요소를 일괄적으로 변경하는데 효과적이다.
// 수를 요소로 갖는 배열을 입력받아
// 각 요소를 2배 곱한 새로운 배열을 리턴
function getDoubled(arr){
return arr.map (function(el){
return el * 2;
});
}
// 오피스 아워 추가 설명 부분
const arr = [1,2,3,4,5]
const multiplyBy2 = function(value){
return value * 2;
}
multipleBy2(1); //2
multipleBy2(2); //4
// 어떤 로직을 적용했을 때, 그 로직의 결과값들이 담기는 고차함수가 map
// filter는 boolean값을 리턴해야만 하는 메소드였고,
// 참이냐 거짓이냐에 따라서 filter가 되냐 안되냐를 구분했지만
// map은 그것과 상관없이 다양한 로직을 담을 수 있다.
arr.map(multipleBy2); //[2,4,6,8,10]
const changeToObject = function(value){
return{
value: value;
}
}
changeToObject(1);//{value:1}
arr.map(changeToObject) ; // {value: 1}
{value: 2}
{value: 3}
...
어떤 하나의 배열을 하나의 수로 줄이는 것.
// number타입을 요소로 갖는 배열을 입력받아 배열의 모든 요소의 합을 리턴
function computeSumofAll(arr){
return arr.reduce(function (acc, cur){
return acc + cur;
}, 0);
}
// 오피스 아워 추가 설명 부분
// 어떤 하나의 배열을 하나의 수로 줄이는 것을 reduce라고 한다
const accumulateSum = function(누적값, 엘리먼트){
return 누적값 + 엘리먼트
}
accumulateSum(0, 1); //1
accumulateSum(accumulateSum(0,1), 2); //3
accumulateSum(accumulateSum(accumulateSum(0,1),2),3); //6
arr.reduce(accumulateSum);//15
const arr = [1,2,3,4,5]
fuction accumulateFilterResult (acc, val){
if(val % 2 === 0){
acc.push(val)
}
return acc;
}
arr.reduce(accumulateFilterResult, []); //[2,4]
// '[]초기값: arr을 accumulateFilterResult를 거쳐서 []에 넣어줄거야'라는 의미
좋은 글 감사합니다!
출처 남기고 공부한 내용 블로그에 정리하려는데 가능하실까요~?