고차 함수 (Higher-order function)

지은·2022년 9월 20일
1

JavaScript

목록 보기
25/42

일급 객체 (first-class citizen)

JavaScript의 대표적인 일급 객체 중 하나인 함수는 특별한 취급을 받는다.

1. 변수에 할당(assignment)할 수 있다.

  • 함수를 변수에 할당할 수 있기 때문에, 배열의 요소나 객체의 속성값으로 저장할 수 있다.
  • 함수를 데이터(string, number, boolean, array, object)처럼 다룰 수 있다.
const square = function(num) {
	return num * num;
}

let output = square(4); // 16
// 변수 square에는 함수가 할당되어 있으므로(일급 객체), 함수 호출 연산자 '()'를 사용할 수 있다.

2. 다른 함수에 전달인자(argument)로 전달될 수 있다.

3. 다른 함수의 결과로서 리턴될 수 있다.

고차 함수를 쓸 수 있는 이유

: 함수가 일급 객체여서!


고차 함수 (higher-order function)

: 함수를 전달인자(argument)로 받을 수 있고, 함수를 리턴할 수 있는 함수

1. 함수를 전달인자로 받는 경우

function double(num) {
	return num * 2;
}

function doubleNum(func, num) { // 콜백 함수 func을 전달인자로 받는 고차 함수 doubleNum
	return func(num);
}

let output doubleNum(double, 4); // 8
  • 이때 전달인자로 전달되는 함수를 콜백 함수라고 부른다.
  • 콜백 함수를 전달받은 고차 함수(caller)는, 함수 내부에서 이 콜백 함수를 호출할 수 있고, 조건에 따라 콜백 함수의 실행 여부를 결정할 수도 있다.

콜백 함수(callback function)

: 다른 함수(caller)에 전달인자로 전달되는 함수
어떤 작업이 완료되었을 때 호출하는 경우가 많아, "답신 전화"라는 뜻의 콜백 함수라는 이름이 붙여졌다.


2. 함수를 리턴하는 경우

function adder(added) {
	return function(num) { // 익명 함수를 리턴하는 고차 함수이자 커링 함수 adder
    	return num + added; 
    }
}

let output = adder(5)(3); // 8

const add3 = adder(3); // adder가 리턴하는 함수를 변수에 저장할 수 있다.(함수는 일급 객체이므로)
output = add3(2);      // 5

커링 함수(curring function)

: 함수를 리턴하는 함수
커링 함수라는 용어를 사용하는 경우에는, 고차 함수라는 용어를 "함수를 전달인자로 받는 함수"에만 한정해 사용하기도 한다.
그러나 정확하게 구분하자면, 고차 함수가 커링 함수를 포함한다.


3. 함수를 전달인자로 받고, 함수를 리턴하는 경우

function double(num) {
	return num * 2;
}

function doubleAdder(added, func) { // 콜백 함수 func을 전달인자로 받고,
	const doubled = func(added);
    return func(num) {              // 전달받은 함수를 리턴하는 고차 함수 doubleAdder 
    	return doubled + num;
    }
}

doubleAdder(5, double)(3); // 10 + 3 = 13

const addTwice3 = doubleAdder(3, double); // doubleAdder가 리턴하는 함수를 변수에 저장할 수 있다. (함수는 일급 객체이므로)
addTwice3(2); // 6 + 2 = 8

내장 고차 함수

JavaScript에는 기본적으로 내장된 고차 함수가 있다.
그 중에서 배열 메소드 중 일부가 대표적인 고차 함수에 해당한다.
ex. filter, map, reduce, forEach, find, sort, some, every ...


filter

arr.filter(fn) : 배열의 각 요소를 콜백 함수에 전달해 true를 반환하는 요소들만 새로운 배열로 만들어 반환하는 메소드

const isEven = function(num) {
	return num % 2 === 0; // true나 false를 반환한다.
}

const arr = [1, 2, 3, 4, 5];
const output = arr.filter(isEven); // [2, 4]

filter 메소드가 고차 함수인 이유

filter 메소드의 전달인자로 함수를 전달하기 때문 (콜백 함수)

filter 메소드가 동작하는 방식

Array.prototype.filter = function(func) {
  const arr = this;
  const newArr = []
  for(let i = 0; i < arr.length; i++) {
    if (func(arr[i]) === true) {
      newArr.push(this[i])
    }
  }
  return newArr;
}

map

arr.map(fn) : 배열의 각 요소에 콜백 함수에 적용시켜 새로운 배열로 만들어 반환하는 메소드

const multiply2 = function(num) {
	return num * 2;
}

const arr = [1, 2, 3, 4, 5];
const output = arr.map(multiply2); // [2, 4, 6, 8, 10]
  • 콜백 함수에 두 번째 전달인자를 줄 경우 index를 가져온다.
const multiply3 = function(num, idx) {
	return `${idx}: ${num * 3}`;
}

const arr = [1, 2, 3, 4, 5];
const output = arr.map(multiply3); 
// ['0: 3', '1: 6', '2: 9', '3: 12', '4: 15']

reduce

arr.reduce(fn) : 배열의 각 요소를 콜백 함수에 맞게 하나로 응축시킨 값을 리턴하는 메소드

  • accmulator : 누산값
  • currentValue : 현재값 (현재 배열 요소)
  • initialValue : 초기값
    초기값을 설정하면 초기값이 첫 번째 acc가 된다.
    초기값을 설정하지 않으면 배열의 첫 번째 요소가 acc가 된다.
const arr = [1, 2, 3, 4, 5];

arr.reduce((acc, cur) => {
	return acc + cur;
}, initialValue) // 15

every

arr.every(fn) : 배열 안의 모든 요소가 콜백 함수를 통과하면 true, 하나라도 통과하지 못하면 false를 반환하는 메소드

const arr = [1, 2, 3, 4, 5];

arr.every((el) => el < 10); // true
arr.every((el) => el < 5);  // false

sort

arr.sort(compareFn) : 배열의 요소를 정렬한 후 원 배열을 반환하는 메소드

  • 매개변수로 compare 함수를 전달하지 않고 생략하면, 요소를 문자열로 변환한 후, 문자의 유니 코드 코드 포인트 순서에 따라 정렬한다.
const arr = [5, 3, 4, 2, 1, 10];
arr.sort(); // [1, 10, 2, 3, 4, 5]
// 문자열 "10"은 유니 코드 순서에서 "2" 앞에 온다. 

const arr = ['d', 'a', 'c', 'e', 'b'];
arr.sort(); // ['a', 'b', 'c', 'd', 'e']
  • 숫자를 비교하고 싶다면 compare 함수를 a - b를 리턴하도록 하면 된다.
    다음 함수는 배열을 오름차순으로 정렬한다. (InfinityNaN이 포함되어 있지 않은 경우)
const arr = [5, 3, 4, 2, 1, 10];
arr.sort((a, b) => a - b); // [1, 2, 3, 4, 5, 10]

❔ 학습 후 궁금한 점

  • 커링 함수? 클로저 함수?
  • 새로운 배열을 반환한다. = immutable?
  • 메서드와 함수의 차이는 무엇인지?
profile
개발 공부 기록 블로그

0개의 댓글