고차함수

Stella·2021년 7월 12일
0

First-class citizen


자바스크립트에도 특별한 대우를 받는 일급 객체(first-class citizen)가 있습니다. 대표적인 일급 객체 중 하나가 함수입니다. (자바스크립트가 나온 시점을 고려했을 때,) 자바스크립트에서 함수는 아래와 같이 특별하게 취급됩니다.

  • 변수에 할당(assignment) 할 수 있다.
  • 다른 함수의 인자(argument)로 전달될 수 있다.
  • 다른 함수의 결과로서 리턴될 수 있다.

함수를 변수에 할당할 수 있기 때문에, 함수배열의 요소나 객체의 속성값으로 저장할 수 있습니다. 이는 함수를 데이터(string, number, boolean, array, object)를 다루듯이 다룰 수 있다는 걸 의미합니다.

고차함수


고차 함수(higher order function)는 함수를 인자(argument)로 받을 수 있고, 함수의 형태로 리턴할 수 있는 함수입니다

이때 다른 함수(caller)의 인자(argument)로 전달되는 함수를 콜백 함수(callback function)라고 합니다.

1. 다른 함수를 인자로 받는 경우

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

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

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

Map 함수


map 함수는 모든 요소에게 동일한 행동을 주는 값에대하여 모두 반환하고 callbackFunction 을 실행한 결과를 가지고서 새로운 배열을 만들 때도 사용 합니다.

구문

array.map(callbackFunction(currentValute,index,array), thisArg

map 함수에는 callbackFunction, thisArg 두 개의 매개변수가 있고

callbackFunctioncurrentValue, index, array 3개의 매개변수를 갖습니다.

currentValue : 배열 내 현재 값

index : 배열 내 현재 값의 인덱스

array : 현재 배열.

thisArg : callbackFunction 내에서 this로 사용될 값

사용예시


1. 각 요소에 2배씩 곱하기

let numbers = [1,2,3,4,5];
let result = numbers.map(double => double * 2);
console.log(result); //  [2, 4, 6, 8, 10]

2. 각 배열의 길이 값 구하기

let animals = ['cat','lion','tiger','snake','dog'];
let result = animals.map(animal => animal.length);
console.log(result); // [3, 4, 5, 5, 3]

3. 각 요소의 제곱근 구하기

let numbers = [1,4,9,16,25,36];
let result = numbers.map(Math.sqrt);
console.log(result); //  [1, 2, 3, 4, 5, 6]

Filter 함수


filter 함수는 callbackFunction의 조건에 해당하는 모든 요소가 있는 배열을 새로운 배열로 반환 합니다.

구문

array.filter(callbackFunction(element, index, array), thisArg);

filter 함수에는 callbackFunction, thisArg 두 개의 매개변수가 있고

callbackFunctionelement, index, array 3개의 매개변수를 갖습니다.

element : 요소값

index: 요소의 인덱스

array : 사용되는 배열 객체

thisArg : callbackFunction 내에서 this로 사용될 값

사용예시


1. 문자열의 길이가 6이상만 출력

const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

const result = words.filter(word => word.length => 6); //  ["exuberant", "destruction", "present"]

2. 특정 문자만 추출 하기

const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

const result = words.filter(word => word === 'limit'); // ["limit"]

Reduce 함수

reduce 함수는 배열을 하나의 값으로 만들어 줍니다.
또한 reduce는 초기값을 정할 수 있는대 정하지 않는다면 첫 번째 요소가 초기값이 됩니다

구문

 array.reduce(function callbackFn(accumulator, currentValue, index, array){...}, initialValue)

reduce함수에는 callbackfunctioninitialValue 2개의 매개변수가 있고

callbackFunctionaccumulator, currentValue, currentIndex, array 4개의 매개변수를 선택적으로 받을 수 있습니다.

accumulator 는 배열의 첫번째 인자, 혹은 initialValue가 있을경우 initialValue.

currentValue 는 배열 내 현재 처리되고 있는 값.

currentIndex 는 배열 내 현재 처리되는 있는 값의 인덱스.

array 는 현재 호출된 배열 입니다.

그리고 initialValue 은 최초 호출에서 첫 번째 인수에 제공하는 값. 초기값을 제공하지 않으면 배열의 첫 번째 요소를 사용합니다. 빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생합니다.

사용 예시


1. 입력값을 누적해서 더하기

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

let result = arr.reduce((acc, cur, idx) => { return acc + cur } );

console.log(result) // 15
  1. 배열을 문자열로
function joinName(resultStr, user) {
  resultStr = resultStr + user.name + ', ';
  return resultStr;
}

let users = [
  { name: 'Tim', age: 40 },
  { name: 'Satya', age: 30 },
  { name: 'Sundar', age: 50 }
];

users.reduce(joinName, ''); //  "Tim, Satya, Sundar, "
function makeAddressBook(addressBook, user) {
  let firstLetter = user.name[0];

  if(firstLetter in addressBook) {
    addressBook[firstLetter].push(user);
  } else {
    addressBook[firstLetter] = [];
    addressBook[firstLetter].push(user);
  }

  return addressBook;
}

let users = [
  { name: 'Tim', age: 40 },
  { name: 'Satya', age: 30 },
  { name: 'Sundar', age: 50 }
];

users.reduce(makeAddressBook, {});

리턴값

{
  T: [
    { name: 'Tim', age: 40 }
  ],
  S: [
    { name: 'Satya', age: 30 },
    { name: 'Sundar', age: 50 }
  ]
}
profile
메모장 쓰면서 공부중

0개의 댓글