[JavaScript] 내장 고차 함수

Hannahhh·2022년 7월 21일
0

JavaScript

목록 보기
25/47

🔍 내장 고차 함수?

JavaScript에는 기본적으로 내장된 고차 함수가 여러 개 존재한다. 그 대표적인 고차함수로 배열 메서드 중 일부를 들을 수 있다.


✔ filter

모든 배열의 요소 중에서 특정 조건을 만족하는 요소를 걸러내는 메서드이다.(기존 배열 변경 XX)

걸러내는 기준이 되는 특정 조건은 filter 메서드의 전달인자로 전달되며, 함수의 형태를 갖는다. 따라서, filter 메서드는 걸러내기 위한 조건을 명시한 함수를 전달인자로 받기 때문에 고차함수이다.


filter 메서드가 동작하는 방식은 아래와 같다.

// 아래 코드는 정확한 표현 방식은 아닙니다.
// 의미만 이해해도 충분합니다.

let arr = [1, 2, 3];
// 배열의 filter 메서드는 함수를 전달인자로 받는 고차 함수입니다.
// arr.filter를 실행하면 내부적으로 arr에 접근할 수 있다고 생각해도 됩니다.
arr.filter = function (arr, func) {
  const newArr = [];
  for (let i = 0; i < arr.length; i++) {
    // filter에 전달인자로 전달된 콜백 함수는 arr의 각 요소를 전달받아 호출됩니다.
    // 콜백 함수가 true를 리턴하는 경우에만 새로운 배열에 추가됩니다.
    if (func(arr[i]) === true) {
      newArr.push(this[i]);
    }
  }
  // 콜백 함수의 결과가 true인 요소들만 저장된 배열을 리턴합니다.
  return newArr;
};

/*
 * filter 메서드의 보다 정확한 정의는 아래와 같습니다. 아래 코드를 이해하기 위해서는 다음 유닛에서 프로토타입과 this에 대한 학습이 필요합니다.
 * 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;
 * }
 */

filter 메서드의 사용 예시는 아래와 같다.



// Example 1

// 함수 표현식
const isEven = function (num) {
  return num % 2 === 0;
};

let arr = [1, 2, 3, 4];
// let output = arr.filter(짝수);
// '짝수'를 판별하는 함수가 조건으로서 filter 메서드의 전달인자로 전달됩니다.
let output = arr.filter(isEven);
console.log(output); // ->> [2, 4]


// Example 2

const isLteFive = function (str) {
  // Lte = less then equal
  return str.length <= 5;
};

arr = ['hello', 'code', 'states', 'happy', 'hacking'];
// output = arr.filter(길이 5 이하)
// '길이 5 이하'를 판별하는 함수가 조건으로서 filter 메서드의 전달인자로 전달됩니다.
let output = arr.filter(isLteFive);
console.log(output); // ->> ['hello', 'code', 'happy']


// Example 3

// 만화책 식객 27권의 정보가 배열에 담겨있습니다.
// 출판 연도가 2003년인 단행본만 담은 배열을 만드세요.

//수도코드
/* 배열의 각 요소 : 각 식객 1 -27권의 정보
   특정 논리(함수): 책의 출판 연도가 2003년 입니다.(true/false)
   따로 분류(filter): 출판 연도가 2003년인 책의 정보
*/

const cartoons = [
  {
    id: 1,
    bookType: 'cartoon',
    title: '식객',
    subtitle: '어머니의 쌀',
    createdAt: '2003-09-09',
    genre: '요리',
    artist: '허영만',
    averageScore: 9.66,
  },
  {
    id: 2,
    // .. 이하 생략
  },
  // ... 이하 생략
]; 

// 단행본 한 권의 출판 연도가 2003인지 확인하는 함수
const isCreatedAt2003 = function (cartoon) {
  const fullYear = new Date(cartoon.createdAt).getFullYear()
  return fullYear === 2003;
}; 

// 출판 연도가 2003년인 책의 모음
const filteredCartoons = cartoons.filter(isCreatedAt2003); 



✔ map

하나의 데이터를 다른 데이터로 mapping할 때 사용되는 메서드로, 모든 요소에게 동일한 행동을 준 값에 대하여 모두 반환한다. (기존 배열 변경 XX)

걸러내는 기준이 되는 특정 조건은 filter 메서드와 마찬가지로 전달인자로 전달되며, 함수의 형태를 갖는다.


map 메서드의 사용 예시는 아래와 같다.

// Example

// 만화책 식객 27권의 정보가 배열에 담겨있습니다. 
// 각 책의 부제(subtitle)만 담은 배열을 만드세요.

/*
수도코드:
배열의 각 요소: 각 식객 1-27권의 정보
특정 논리(함수): 책 한 권의 부제를 찾습니다
다른 요소로 지정: 각 식객 1-27권의 부제
*/

// 만화책 모음
const cartoons = [
  {
    id: 1,
    bookType: 'cartoon',
    title: '식객',
    subtitle: '어머니의 쌀',
    createdAt: '2003-09-09',
    genre: '요리',
    artist: '허영만',
    averageScore: 9.66,
  },
  {
    id: 2,
    // .. 이하 생략
  },
  // ... 이하 생략
]; 

// 만화책 한 권의 부제를 리턴하는 로직(함수)
const findSubtitle = function (cartoon) {
  return cartoon.subtitle;
}; 

// 각 책의 부제 모음 
const subtitles = cartoons.map(findSubtitle); // ['어머니의 쌀', ...]



✔ reduce

여러 데이터를 하나의 데이터로 응축(reduce)할 때 사용한다.
reduce는 초기값을 설정할 수 있으며, default는 배열의 첫 번째 값이다.

초기값은 누적값의 기반이 되며 그 다음 요소부터는 현재값이 된다. 현재값은 조건(특정 방법)에 의하여 누적값에 저장이된다.(조건은 배열의 끝까지 반복)

  • 문자열, 숫자의 합치기 or 빼기
    [1, 2, 3] > .reduce(sum,1) > 7

  • 제일 작은 것 or 큰 것 비교
    [9, -1, 54] > .reduce(the smallest) > -1
    (* the smallest = callback function)

  • 배열 의외의 다른 형태로 만들기 등 활용 범위가 높다.
    ['a', 2, 99] > .reduce(classByType, {}) > {string: 'a', number: 2, 99}
    (* classByType = callback function)


reduce 메서드의 사용 예시는 아래와 같다.


//Example 1: 배열 요소(숫자)의 합구하기

//만화책 식객 27권의 정보가 배열에 담겨있습니다. 
//각 단행본의 평점의 평균을 리턴하세요.

/*
수도코드:
배열의 각 요소: 각 식객 1-27권의 정보
응축하는 방법(함수): 각 단행본의 평점을 누적값에 더한다.
원하는 형태: 숫자로 누적한다.
응축된 결과: 각 단행본의 평점의 합을 단행본의 길이로 나눈 평점의 평균
*/

// 단행본 모음
const cartoons = [
  {
    id: 1,
    bookType: 'cartoon',
    title: '식객',
    subtitle: '어머니의 쌀',
    createdAt: '2003-09-09',
    genre: '요리',
    artist: '허영만',
    averageScore: 9.66,
  },
  {
    id: 2,
    // .. 이하 생략
  },
  // ... 이하 생략
];

// 단행본 한 권의 평점을 누적값에 더한다.
const scoreReducer = function (sum, cartoon) {
  return sum + cartoon.averageScore;
}; 

// 초기값에 0을 주고, 숫자의 형태로 평점을 누적한다.
let initialValue = 0 
// 모든 책의 평점을 누적한 평균을 구한다.
const cartoonsAvgScore = cartoons.reduce(scoreReducer, initialValue) / cartoons.length;




// Example 2: 배열을 문자열로 바꾸기

/*
수도코드:
배열의 각 요소: 유저 정보
응축하는 방법(함수): 하나의 유저의 이름과 쉼표를 이어 붙입니다(concat)
원하는 형태: 문자열로 누적합니다.
응축된 결과: 쉼표로 구분되는 모든 유저의 이름
*/

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, '



//Example 3: 배열을 객체로 바꾸기

/*
배열의 각 요소: 유저 정보
응축하는 방법(함수): 유저 한 명의 이름 중 첫 글자를 주소록 객체 속성의 키(key)로, 유저의 정보를 주소록 객체 속성의 값(value)으로 추가합니다.
원하는 형태: 주소록 객체에 누적합니다.
응축된 결과: 모든 유저의 정보가 알파벳으로 구분된 주소록
*/

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 }
  ]
}
*/



✔ forEach

for문을 대체하는 고차 함수로, 주어진 함수를 배열 요소 각각에 대해 실행한다.(반복문의 추상화)

const items = ['item1', 'item2', 'item3'];
const copy = [];

items.forEach(item =>{copy.push(item);}) //빈 배열 copy에 item의 요소들을 하나씩 할당

console.log(copy); // [ 'item1', 'item2', 'item3' ]



✔ find

주어진 callback 함수를 만족하는 첫 번째 요소의 값을 반환한다. (default undefined를 반환)

const array = [5, 12, 8, 130, 44];

const found = array.find(element => element > 10);

console.log(found); //12



✔ sort

배열의 요소를 적절한 위치에 정렬한 후 그 배열을 반환한다. 기본 정렬 순서는 문자열의 유니코드 코드 포인트를 따르기 때문에, 숫자를 정렬할때는 callback 함수가 제공되어야 한다.

var numbers = [4, 2, 5, 20, 50, 40];
numbers.sort(function(a, b) {
  return a - b; //오름차 순으로 정렬(a-b가 음수면 b가 먼저), 내림차 순: b-a
});
console.log(numbers);



✔ some

배열 안의 어떤 요소라도 주어진 callbck 함수를 통과하는지 테스트하며, Bollean 값을 반환한다.(하나라도 통과하면 true, 아니면 false)

빈 배열에서 호출 시, 무조건 false를 반환한다.

var fruits = ['apple', 'banana', 'mango', 'guava'];

function checkAvailability(arr, val) {
    return arr.some(arrVal => val === arrVal);
}

checkAvailability(fruits, 'kela'); //false
checkAvailability(fruits, 'banana'); //true



✔ every

배열 안의 모든 요소가 주어진 판별 함수를 통과하는지 테스트하며,Boolean 값을 반환한다.


const array = [1, 30, 39, 29, 10, 13];

const isBelowThreshold = (currentValue) => currentValue < 40;

console.log(array.every(isBelowThreshold)); //true




Reference:
코드스테이츠
MDN

0개의 댓글