2022-01-04 T.I.L

정종훈·2022년 3월 1일
0

T.I.L

목록 보기
3/20

고차함수

함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수라고 하며
매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를
고차 함수(Higher-Order Function)라고 한다.


일급객체의 3가지 특징

  1. 변수에 할당 가능
  1. 다른 함수의 인자로 전달 가능
  1. 다른 함수의 결과로써 리턴 가능

=> 따라서 JS에서 함수는 일급 객체


고차함수란?

  • 함수를 인자로 받는 함수

Example 1) 함수를 인자로 받는다는건...callback이란 느낌일까?

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

function doubleNum(func, num) {
  return func(num);
}

/*
 * 함수 doubleNum은 다른 함수를 인자로 받는 고차 함수입니다.
 * 함수 doubleNum의 첫 번째 인자 func에 함수가 들어올 경우
 * 함수 func는 함수 doubleNum의 콜백 함수입니다.
 * 아래와 같은 경우, 함수 double은 함수 doubleNum의 콜백 함수입니다.
 */
let output = doubleNum(double, 4);
console.log(output); // -> 8
  • 함수를 리턴하는 함수

Example 2) 함수를 리턴한다는건...커리함수일까?...

function adder(added) {
  return function (num) {
    return num + added;
  };
}

/*
 * 함수 adder는 다른 함수를 리턴하는 고차 함수입니다.
 * adder는 인자 한 개를 입력받아서 함수(익명 함수)를 리턴합니다.
 * 리턴되는 익명 함수는 인자 한 개를 받아서 added와 더한 값을 리턴합니다.
 */

// adder(5)는 함수이므로 함수 호출 연산자 '()'를 사용할 수 있습니다.
let output = adder(5)(3); // -> 8
console.log(output); // -> 8

// adder가 리턴하는 함수를 변수에 저장할 수 있습니다.
// javascript에서 함수는 일급 객체이기 때문입니다.
const add3 = adder(3);
output = add3(2);
console.log(output); // -> 5

커리함수 : 함수를 리턴하는 함수(ex2에서는 adder함수)

  • 듀다(베컴말투로)

Example 3) 함수를 인자로 받고, 함수를 리턴하는 경우

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

function doubleAdder(added, func) {
  const doubled = func(added);
  return function (num) {
    return num + doubled;
  };
}

/*
 * 함수 doubleAdder는 고차 함수입니다.
 * 함수 doubleAdder의 인자 func는 함수 doubleAdder의 콜백 함수입니다.
 * 함수 double은 함수 doubleAdder의 콜백으로 전달되었습니다.
 */

// doubleAdder(5, double)는 함수이므로 함수 호출 기호 '()'를 사용할 수 있습니다.
doubleAdder(5, double)(3); // -> 13

// doubleAdder가 리턴하는 함수를 변수에 저장할 수 있습니다. (일급 객체)
const addTwice3 = doubleAdder(3, double);
addTwice3(2); // --> 8

배열내장 고차함수

들어가기 전에

메소드는 객체에 들어있는 함수이다.

예를들어 arr.map을 쓰는데 사실은 arr.prototype.map 이고 arr["map"] 도 통한다.

여기서 prototype은 원형객체라고 한다.

Array.prototype.map

  • map 메서드는 자신을 호출한 배열의 모든 요소를 순환하면서 인수로 전달받은 콜백 함수를 반복 호출한다.

그리고 콜백 함수의 반환값들로 구성된 새로운 배열을 반환한다. 바꾸기 ! 이때 원본 배열은 인정되지 않는다.

arr.map(callback(currentValue[, index[, array]])[, thisArg])

Exmaple 4) 맵 메서드의 기본 사용법

let arr = [1, 2, 3, 4, 5]

let arr1 = arr.map(el => el * 3);

console.log(arr1); //[3, 6, 9, 12, 15]

콜백함수에 두번째 인자를 줄 경우 인덱스를 가져 온다.


Example5) 인덱스를 쓸 경우

let arr = [2, 4, 6]

let arr1 = arr.map((el, i) => `${i}번째 인덱스의 값은: ${el * 3} `)

console.log(arr1); //[ '0번째 인덱스의 값은: 6 ', '1번째 인덱스의 값은: 12 ', '2번째 인덱스의 값은: 18 ' ]

Array.prototype.filter

  • filter 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출한다.

그리고 콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환한다. 거름망 ! 원본 배열 인정 안함.

arr.filter(callback(element[, index[, array]])[, thisArg])

Example 6) 필터 메서드의 기본 사용법

let arr = [1, '2', '5,', undefined];

let arr1 = arr.filter(el => typeof (el) === 'string');
 
console.log(arr1); //[ '2', '5,' ]


Array.prototype.reduce

  • reduce 메서드는 자신을 호출한 배열을 모든 요소를 순회하며 인수로 전달받은 콜백 함수를 반복 호출한다.

그리고 콜백 함수의 반환값을 다음 순회 시에 콜백 함수의 첫 번째 인수로 전달하면서 콜백 함수를 호출하여 하나의 결과값을 만들어 반환한다.
하나의 값으로 응축!
. 이떄 원본 배열은 변경되지 않는다.

Array.reduce( (acc, cur, index, arr  ) => {결과값}, 초깃값)

acc : 콜백반환값을 누적한다. 정하지 않으면 배열의 첫번쨰요소이다.

cur : 현재값. i번째 인덱스의 값이다. 정하지 않으면 배열의 두번째 요소이다.

초깃값: 보통 배열을 리턴하려면 [], 개게를 리턴하려면 {}형태를 준다. 정하지 않은경우 배열의 첫번쨰 요소가 초깃값이다.

  • reduce 메서드의 실행순서
  1. acc, cur 확인
  1. 콜백함수실행
  1. 2의 결과가 acc가 됨
  1. 무한반복 언제까지? 다음 cur이 없을때 까지
  1. 응축 값 리턴

Example 7) 요소의 중복횟수 구하기

const fruits = ['banana', 'apple', 'orange', 'orange', 'apple'];

const count = fruits.reduce((acc, cur) => {
// 순회 시 프로퍼티 값이 undefined이면 (acc[cur]이) 0으로 카운트하고 1을 더해줌
// 만약 프로퍼티 값이 존재하면 기존의 프로퍼티값에 1을 더해줌.
    acc[cur] = (acc[cur] || 0) + 1;
    return acc
}, {})

console.log(count); //{ banana: 1, apple: 2, orange: 2 }

기타(악기아님 ㅎ) 배열고차함수

  • arr.foreach : 요소를 돌리면서 조작 . for 문을 대체하는 고차함수
  • arr.sort : 정렬 특히 오름차순 내림차순은 외우기
  • arr.find : 조건에 맞는 단 하나 찾고 반복문 종료
  • arr.every : 배열안의 모든 요소가 조건을 만족하면 true
  • arr.some : 배열안의 어떤 요소가 조건을 만족하면 true

Example) 사고 수준의 추상화의 예시

const data = [
  {
    gender: 'male',
    age: 24,
  },
  {
    gender: 'male',
    age: 25,
  },
  {
    gender: 'female',
    age: 27,
  },
  {
    gender: 'female',
    age: 22,
  },
  {
    gender: 'male',
    age: 29,
  },
];

Example)

unction getAverageAgeOfMaleAtOnce(data) {
  const onlyMales = data.filter(function (d) {
    // data.filter는 배열의 각 요소에 인자로 전달받은 함수를 적용하고,
    // 그 결과가 true인 요소만을 갖는 배열을 리턴합니다.
    return d.gender === 'male';
  });

  const numOfMales = onlyMales.length;

  const onlyMaleAges = onlyMales.map(function (d) {
    // onlyMales.map는 배열의 각 요소에 인자로 전달받은 함수를 적용하고,
    // 각 결과를 요소로 갖는 배열을 리턴합니다.
    return d.age;
  });

  const sumOfAges = onlyMaleAges.reduce(function (acc, cur) {
    // onlyMaleAges.reduce는 배열의 각 요소에 인자로 전달받은 함수를 적용하고,
    // 각 결과를 두 번째 인자로 전달받은 초기값(0)에 누적한 결과를 리턴합니다.
    return acc + cur;
  }, 0);

  return sumOfAges / numOfMales;
profile
괴발개발자에서 개발자로 향해보자

0개의 댓글