[JavaScript] Higher Order Function

Steve·2021년 4월 28일
0

웹개발 코스

목록 보기
14/59
  1. 일급 객체(first-class citizen)의 세 가지 특징을 설명할 수 있다.
  2. 고차 함수(higher-order function)에 대해 설명할 수 있다.
  3. 고차 함수를 자바스크립트로 작성할 수 있다.

First-class citizen (일급 객체)

프로그래밍에서 "일급 객체"는 다른 요소의 특징을 가진 객체를 뜻한다. 자바스크립트 함수는 일급 객체다. 그 이유는:
1. 함수를 변수에 할당하여 변수처럼 취급할 수 있다. (함수표현식, Function Expression)
2. 함수를 다른 함수의 인자로 전달할 수 있다.
3. 함수가 다른 함수의 결과값으로 리턴될 수 있다.

고차함수(higher order function)

함수를 반환하는 함수 혹은 함수를 인자로 받는 함수.
다른 함수(=caller)의 인자로 전달되는 함수를 콜백 함수(callback)이라고 한다. Callback은 답신 전화를 뜻하며, 어떤 작업이 완료되었을 때 호출되는 경우가 많아서 그런 이름이 붙여졌다.
함수를 반환하는 함수는 이를 고안해 낸 논리학자 Haskell Curry 의 이름을 따 Curry 함수라고 부르기도 한다.

고차함수 만들어보기

// 1.함수를 인자로 받는 함수
function square(a) { return a * a; }
function squareNumber(func, num) { return func(num); }
squareNumber(square, 4); // 8
// squareNumber 고차함수가 되고, square를 인자로 받으면 square는 callback 함수가 된다.

// 2. 함수를 리턴하는 함수
function multiplier(num1) {
  return function (num2) {
    return num1 * num2;
  }
}
multiplier(3)(2); // 6
let multiply2 = multiplier(2);
multiply2(7); // 14

// 3. 두개를 섞을 수도 있다. 굳이 만들지는 않는다.

JavaScript 고차함수

추상화(abstraction)에 대해 설명할 수 있다.
추상화의 관점에서 고차 함수가 갖는 이점에 대해 설명할 수 있다.
배열 내장 고차함수를 이해할 수 있다.(filter, map, reduce 등)

추상화(abstraction)

"Another level of abstraction!" - Carrie Anne from PBS CS

추상화는 복잡한 어떤 것을 압축해서 핵심만 추출한 상태를 만드는 것.
예) CPU를 만들면 그걸 가지고 컴퓨터를 만들 수 있다.
추상화를 통해 더 복잡한 것을 만들 수 있다. 그리고 그걸 또 추상화하여 더 복잡한 것을 만든다.

프로그래밍에서 추상화는 함수를 만들어 쓰는 것을 예시로 들 수 있겠다.
일반 함수 : 값을 전달받아 처리한다. (처리 과정을 추상화)
고차 함수 : 함수를 전달받아 처리한다. 혹은 함수를 리턴한다.
즉 고차 함수는 추상화된 것을 받아 또 추상화시키기 때문에 추상화를 한차원 높인 것이라고 할 수 있다. 생산성이 올라간다.

다음 자바스크립트 추상함수들을 알아보자 (filter, map, reduce)

array.filter()

array.filter() 함수는 배열 메소드로, 함수를 인자로 받는다(callback). 배열을 순회하며 배열의 요소를 callback으로 전달한다. callback 은 조건을 제시하여 true/false 를 반환하고, filter는 true인 인자만 들어있는 새 배열을 반환한다.

array.map()

array.map() 함수는 배열 메소드로, 함수를 인자로 받는다(callback). 배열을 순회하며 배열의 요소를 callback 으로 전달한다. callback 은 배열의 요소를 가공하여 반환하고, map은 가공된 요소들이 들어있는 새 배열을 반환한다.

array.reduce()

array.reduce() 함수는 배열 메소드로, 함수를 인자로 받는다(callback). 배열을 순회하며 배열의 요소를 callback 으로 전달한다. 이때 initialValue 값이 없다면 배열의 첫번째 요소가 accmulator 값이 되며, 두번째 요소는 currentValue 값이 된다. callback 은 축적 방식을 제시하며, 한번 축적된 결과를 반환한다. 값을 return 하면 그 값이 accmulator의 값이 된다. reduce 함수는 accumulate 된 하나의 값을 반환한다.
reduce 함수는 다양하게 사용될 수 있는데, 숫자 뿐만 아니라 initialValue 설정에 따라 배열이나 객체를 반환하는 것도 가능하다. ([], {})

reduce 깊게 파기

initialValue 를 제시하지 않으면 에러가 날 확률이 있으므로 항상 제시하는 것이 좋다. [ reduce initialValue | MDN ]

배열의 길이initialValueresult
0없음TypeError
0있음initialValue 반환
1없음callback 호출 없이 유일한 요소 반환

다루어야 할 숫자가 배열 내 객체에 들어있을 경우map을 써서 빼내준 다음 reduce 하면 에러를 줄일 수 있고 원하는 결과를 쉽게 예측할 수 있다.
다음은 MDN 문서에 있는 "더 나은 코드"이다.

// map & reduce with initialValue.
// better solution, also works for empty or larger arrays
[ { x: 22 }, { x: 42 } ].map( el => el.x )
                        .reduce( maxCallback2, -Infinity );
// 초기값을 -Infinity 를 주어서 어떤 상황이든 대응한다.

Further Study

  • MapReduce 학습하기 (MapReduce Model)
  • 자바스크립트에서 커링(currying)과 클로저(closure)의 차이 이해하기 (js closure vs curry)
  • 선언형 프로그래밍(declarative programming)과 절차형 프로그래밍(imperative programming)의 차이를 배열 메소드를 통해 이해하기 (js imperative vs declarative)
  • 함수의 조합(function composition)에 대해 학습하기 (javascript function composition)

느낀점

  • c++ 에서도 저 세가지가 모두 가능했다. 물론 변수타입을 엄밀하게 따지기 때문에 자바스크립트보다는 조금 복잡하다. #include <functional> 하고 std::functional해서 사용했다. 이해하는데 애먹었던 기억이 난다.
profile
게임과 프론트엔드에 관심이 많습니다.

0개의 댓글