고차 함수(higher-order function)

HanSungUk·2022년 5월 24일
0

Javascript

목록 보기
12/16
post-thumbnail

고차 함수(higher-order function)

현재 코드스테이츠 강의를 통해 프론트엔드를 학습하고 있습니다.
본 포스트는 해당 강의에 대한 내용 정리를 목적으로 합니다.

학습목표

  • 일급 객체(first-class citizen)의 세 가지 특징을 설명할 수 있다.
  • 고차 함수(higher-order function)에 대해 설명할 수 있다.
  • 고차 함수를 자바스크립트로 작성할 수 있다.
  • 배열 내장 고차 함수 filter에 대해서 이해할 수 있다.
  • filter에 대한 이해를 기반으로, 나머지 내장 고차 함수를 학습할 수 있다.
    (filter, map, reduce, forEach, find, sort, some, every)
  • 고차 함수를 쓰는 이유를 설명할 수 있다.
  • 고차 함수를 활용하여 프로그램을 작성할 수 있다.

1. 일급 객체(first-class citizen)

  • 변수에 할당(assignment) 할 수 있다.
    함수를 변수에 할당할 수 있기 때문에, 함수를 배열의 요소나 객체의 속성값으로 저장할 수 있습니다.

  • 다른 함수의 전달인자(argument)로 전달될 수 있다.

  • 다른 함수의 결과로서 리턴될 수 있다.
    함수는 변수에 저장된 데이터를 전달 인자로 받거나, 리턴 값으로 사용할 수 있기 때문에 변수에 할당된 함수를 인자로 받거나, 리턴 값으로 사용할 수 있습니다.

2. 고차 함수의 이해

고차 함수(higher order function)는 함수를 전달인자(argument)로 받을 수 있고, 함수를 리턴할 수 있는 함수입니다.
다른 함수(caller)의 전달인자(argument)로 전달되는 함수를 콜백 함수(callback function)라고 합니다.
어떤 작업이 완료되었을때 호출하는 경우가 많아서, 답신 전화를 뜻하는 콜백 함수라는 이름이 붙여졌습니다.

콜백 함수를 전달받은 고차함수(caller)는 함수 내부에서 이 콜백 함수를 호출(invoke)할 수 있고, 조건에 따라 콜백 함수의 실행 여부를 결정할 수도 있습니다.

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

function doubleNum(func, num) {
  	return func(num);
}
// 험수 doubleNum은 다른 함수를 인자로 받는 고차 함수다.
// 함수 double은 함수 doubleNum의 콜백 함수다.
let output = doubleNum(double, 4);
console.log(output); // 8

커링 함수라고 불리는 '함수를 리턴하는 함수' 또한 넒은 의미로 고차 함수로 불립니다.
고차 함수는 외부 상태의 변경이나 가변(mutable) 데이터를 피하고 불변성(immutablility)을 지향하는 함수형 프로그래밍에 기반을 두고 있습니다.

3. 내장 고차 함수 filter

자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백함수를 반복 호출합니다. 콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환합니다. 이때, 원본 배열이 변경되지 않습니다.

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

// fliter 메서드는 numbers 배열의 모든 요소를 순회하면서 콜백 함수를 반복 호출한다.
// 그리고 콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환한다.
// 다음의 경우 numbers 배열에서 홀수인 요소만 필터링한다.
const odds = numbers.filter(item => item%2);
console.log(odds); // [1, 3, 5]

4. 내장 고차 함수 map

map 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출합니다. 그리고 콜백 함수의 반환값들로 구성된 새로운 배열을 반환합니다. 이때, 원본 배열이 변경되지 않습니다.

const numbers = [1, 4, 9];

// map 메서드는 numbers 배열의 모든 요소를 순회하면서 콜백 함수를 반복 호출한다.
// 그리고 콜백 함수의 반환값들로 구성된 새로운 배열을 반환한다.
const roots = numbers.map(item => Math.sqrt(item));

5. 내장 고차 함수 reduce

reduce 메서드는 자신을 호출한 배열을 모든 요소를 순회하며 인수로 전달받은 콜백 함수를 반복 호출합니다.
그리고 콜백 함수의 반환값을 다음 순회 시에 콜백 함수의 첫 번째 인수로 전달하면서 콜백 함수를 호출하여 하나의 결과값을 만들어 반환합니다. 이때, 원본 배열은 변경되지 않습니다.

// 1부터 4까지 누적을 구한다.
[1, 2, 3, 4].reduce((accumulator, currentValue, index, array) => accumulator + currentValue, 0)
// 위 reduce 메서드는 2개의 인수, 즉, 콜백 함수와 초기값 0을 전달받아 자신을 호출한 배열의 모든 요소를 누적한 결과를 반환합니다. 

const sum = [1, 2, 3, 4].reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 10

const sum = [1, 2, 3, 4].reduce((acc, cur) => acc + cur, 1);
// 여기서 초기값은 1이다.
console.log(sum); // 11

reduce 메서드는 초기값과 배열의 첫 번째 요소값을 콜백 함수에게 인수로 전달하면서 호출하고 다음 순회에는 콜백 함수의 반환값과 두 번째 요소값을 콜백 함수의 인수로 전달하면서 호출합니다. 이 과정을 반복해서 하나의 결과값을 반환합니다.

6. 내장 고차 함수 sort

sort 메서드는 배열의 요소를 정렬합니다. 원본 배열을 직접 변경하며 정렬된 배열을 반환합니다. 기본 정렬은 오름차순 입니다.

const fruits = ['Banana', 'Orange', 'Apple'];

// 오름차순(ascending) 정렬
fruits.sort();

// sort 메서드는 원본 배열을 직접 변경한다.
consol.log(fruits); // ['Apple', 'Banana', 'Orange']

// 내림차순(descending) 정렬
fruits.reverse();

// reverse 메서드도 원본 배열을 직접 변경한다.
console.log(fruits); // ['Orange', 'Banana', 'Apple']

sort 메서드의 기본 정렬 순서는 유니코드 코드 포인트의 순서를 따릅니다. 따라서 숫자 요소를 정렬할 때는 sort 메서드에 정렬 순서를 정의하는 비교 함수를 인수로 전달해야합니다.

const points = [40, 100, 1, 5, 2, 25, 10]

// 숫자 배열의 오름차순 정렬. 비교 함수의 반환값이 0보다 작으면 a를 우선하여 정렬한다.
point.sort((a,b) => a - b);
console.log(points); // [1, 2, 5, 10, 25, 40, 100]

// 숫자 배열의 내림차순 정렬. 비교 함수의 반환값이 0보다 작으면 b를 우선하여 정렬한다.
points.sort((a,b) => b - a);
console.log(points); // [100, 40, 25, 10, 5, 2, 1]

7. 내장 고차 함수 forEach

forEach 메서드는 for문을 대체할 수 있는 고차 함수입니다. forEach 메서드는 자신의 내부에서 반복문을 실행합니다.

const numbers = [1, 2, 3];
const pows = [];

// for문
for(let i =0; i < numbers.length; i++){
	pows.push(numbers[i]**2);
}
console.log(pows); // [1, 4, 9]

// forEach문
numbers.forEach(item => pows.push(item ** 2));
console.log(pows); // [1, 4, 9]

forEach 메서드는 위 예제에서 numbers 배열의 모든 요소를 순회하며 콜백 함수를 반복 호출합니다.
forEach 메서드는 원본 배열(forEach 메서드를 호출한 배열)을 변경하지 않고 undefined를 반환합니다.

8. 내장 고차 함수 some

some 메서드는 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출합니다. 이때 some 메서드는 콜백 함수의 반환값이 단 한 번이라도 참이면 true, 모두 거짓이면 false를 반환합니다. some 메서드를 호출한 배열이 빈 배열이면 false를 반환합니다.

[5, 10, 15].some(item => item > 10); // true

[5, 10, 15].some(item => item < 0) // false

[].some(item => item > 2) // false

9. 내장 고차 함수 every

every 메서드는 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출합니다. 이때 every 메서드는 콜백 함수의 반환값이 모두 참이면 true, 단 하나라도 거짓이면 false를 반환합니다.
every 메서드를 호출한 배열이 빈 배열이면 true를 반환합니다.

[5, 10, 15].every(item => item > 3); // true

[5, 10, 15].some(item => item > 10) // false

[].some(item => item > 2) // true

10. 내장 고차 함수 find

find 메서드는 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출하여 반환값이 true인 첫 번째 요소 를 반환합니다. 콜백 함수의 반환값이 true인 요소가 존재하지 않는다면 undefined를 반환합니다.

// filter 메서드는 배열을 반환한다.
[1, 2, 2, 3].filter(item => item === 2); // [2, 2]

// find 메서드는 요소를 반환한다.
[1, 2, 2, 3].find(item => item === 2); // 2

0개의 댓글