[JS] 고차함수 (higher order function)

아임 레조·2020년 9월 25일
1

STUDY

목록 보기
21/34
post-thumbnail
  • 일급 객체(first-class citizen)의 세 가지 특징을 설명할 수 있다.
  • 고차 함수(higher-order function)에 대해 설명할 수 있다.
  • 추상화(abstraction)에 대해 설명할 수 있다.
  • 추상화의 관점에서 고차 함수가 갖는 이점에 대해 설명할 수 있다.
  • 배열 메소드를 자연스럽게 사용할 수 있다.
  • 고차 함수를 활용하여 프로그램을 작성할 수 있다.

🌇 일급 객체(First-class citizen)

자바스크립트에서 함수는 특별하게 취급한다.

  • 변수에 할당(assignment)할 수 있다.
  • 다른 함수의 인자(argument)로 전달될 수 있다.
  • 다른 함수의 결과로서 리턴될 수 있다.
    이 말인 즉슨, 함수를 데이터(string, number, boolean, array, object)를 다루듯이 다룰 수 있다는 것이다. 변수에 저장할 수 있기 때문에 배열의 요소나 객체의 속성값으로 저장하는 것도 가능하다.

🌆 고차 함수 (Higher order function)

고차 함수는 함수를 인자(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 메소드는 (걸러내기 위한 조건을 명시한) 함수를 인자로 취하기 때문에 고차 함수이다. 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] 
// 가)와 나)는 동일한데 나)를 추상화 한 것이 필터, 가)이다.

🌃 .map

배열의 요소를 일괄적으로 변경하는데 효과적이다.

// 수를 요소로 갖는 배열을 입력받아 
// 각 요소를 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} 
...

🌉 .reduce

어떤 하나의 배열을 하나의 수로 줄이는 것.

// 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를 거쳐서 []에 넣어줄거야'라는 의미 



profile
어쩌다보니 백엔드 개발자/ 번아웃 없이 재밌게 개발하고 싶어요

1개의 댓글

comment-user-thumbnail
2021년 8월 10일

좋은 글 감사합니다!
출처 남기고 공부한 내용 블로그에 정리하려는데 가능하실까요~?

답글 달기