자바스크립트

Section 7. 자바스크립트 고차함수 메서드들

포칼이 2023. 4. 5. 12:04

배열의 고차함수 higher order function 메서드의 특징들은 다음과 같다

  • 다른 함수(콜백 함수)를 인자로 받는다.
  • 함수형 프로그래밍 - 변수 사용 없이 순회 작업들을 코딩한다.

 

1. forEach - 각 요소를 인자로 콜백함수를 실행하는 메서드

  • for문의 좋은 대체제이다.
  • 단점은 예외를 던지지 않으면 종료할 수 없다. - break, continue 사용이 불가하다.

인자들 :

  • 콜백함수 - 인자 : (현재 값, 현재 값의 인덱스, 해당 배열)
  • thisArg

등등이 있다.

 

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

const result = arr.forEach(itm => {
  console.log(itm);
});
//1
//2
//3
//4
//5

콜백함수를 인자로 받았고 forEach를 사용해서 출력이 된 모습이다. 그런데 result자체는 undefined를 반환한다.

// 💡 결과로는 undefined 반환 - 실행 자체를 위한 메서드
console.log('반환값:', result); //반환값: undefined

여기서 forEach는 어떤 작업을 콜백으로 수행하기 위해서 존재한거지 값을 반환한 것이 아니기 때문에 그렇다.

실제 배열을 선언하고 그것으로 작업을 수행하고 결과를 살펴보면 다음과 같다.

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

// 현존하는 함수를 인자로 - 💡 결과 살펴볼 것
arr.forEach(console.log);
//1 0 (5) [1, 2, 3, 4, 5]
//2 1 (5) [1, 2, 3, 4, 5]
//3 2 (5) [1, 2, 3, 4, 5]
//4 3 (5) [1, 2, 3, 4, 5]
//5 4 (5) [1, 2, 3, 4, 5]

이처럼 값이 3가지가 출력이 된다. 첫 번째값은 바로 현재값이다. 두 번째는 현재 값의 인덱스이다. 마지막은 해당 배열이 되겠다.

 

이렇게 console.log 함수를 인자로 넣어버리면 위와 같이 멋대로 3개의 값들이 출력된다. 따라서 forEach를 제대로 쓰려면 콜백함수를 무엇을 쓸 것인지 정확히 해야 한다.

const arr = [10, 20, 30, 40, 50];

// 콜백함수의 인자가 둘일 때
arr.forEach((itm, idx) => {
  console.log(itm, idx);
});
//10 0
//20 1
//30 2
//40 3
//50 4

그러면 위의 예시를 이용해서 이렇게 활용할 수 있다.

const logWithIndex = (itm, idx) => {
  console.log(`[${idx}]: ${itm}`);
}

arr.forEach(logWithIndex);
//[0]: 10
//[1]: 20
//[2]: 30
//[3]: 40
//[4]: 50

2. map - 각 요소를 주어진 콜백함수로 처리한 새 배열을 반환하는 메서드

각 요소를 받아서 어떤 기준으로 그 값을 처리한 다음 각각 기준대로 반환하는 것이다. 

 

인자들 :

  • 콜백함수 - 인자: (현재 값, 현재 값의 인덱스, 해당 배열)
  • thisArg
const orgArr = [1, 2, 3, 4, 5];

// ⭐️ 각 콜백함수는 어떤 값을 반환해야 함
const arr1 = orgArr.map(i => i + 1);
const arr2 = orgArr.map(i => i * i);
const arr3 = orgArr.map(i => i % 2 ? '홀수' : '짝수');

console.log(arr1); //(5) [2, 3, 4, 5, 6]
console.log(arr2); //(5) [1, 4, 9, 16, 25]
console.log(arr3); //(5) ['홀수', '짝수', '홀수', '짝수', '홀수']

여기서 각 콜백함수는 어떤 값을 반환해야 한다는 것을 명심하자. 

그리고 원본이 수정되지 않는다. 새로운 배열을 만드는 것이기 때문이다.

 

다른 예시를 보면

const orgArr = [
  { name: '사과', cat: '과일', price: 3000 },
  { name: '오이', cat: '채소', price: 1500 },
  { name: '당근', cat: '채소', price: 2000 },
  { name: '살구', cat: '과일', price: 2500 },
  { name: '피망', cat: '채소', price: 2500 },
  { name: '딸기', cat: '과일', price: 5000 }
];


const arr1 = orgArr.map(itm => {
  // 💡 블록 안에서는 return 문 필요함
  return {
    name: itm.name,
    cat: itm.cat
  }
});

console.log(arr1);

블럭 안에서는 꼭 return문을 사용해야 한다. 이유는 콜백함수는 값을 반드시 반환해야 하기 때문이다.

 

3. find, findLast, findIndex, findLastIndex - 주어진 기준으로 검색하는 메서드

콜백함수로 인자로 넣었을 때 true를 반환하는 것들은 다음과 같다

  • find - 첫 번째 값 반환
  • findLast - 마지막 값 반환
  • findIndex - 첫 번째 값의 인덱스 반환
  • findLastIndex -  마지막 값의 반환

공통 인자들 : 

  • 콜백함수 - 인자 : (현재 값, 현재 값의 인덱스, 해당 배열)
  • thisArg
const arr = [1, 2, '삼', 4, 5, 6, '칠', 8, 9];

const isString = i => typeof i === 'string';
const isBoolean = i => typeof i === 'boolean';

console.log(
  arr.find(isString),
  arr.findLast(isString),
  arr.findIndex(isString),
  arr.findLastIndex(isString)
); //삼 칠 2 6

만약 없을 경우 값은 undefined, 인덱스는 -1을 반환한다.

// 없을 시 값은 undefined, 인덱스는 -1 반환
console.log(
  arr.find(isBoolean),
  arr.findLast(isBoolean),
  arr.findIndex(isBoolean),
  arr.findLastIndex(isBoolean)
); //undefined undefined -1 -1

 

4. some, every - 어떤/모든 요소가 기준을 충족하는지 확인

콜백함수에 인자로 넣은

  • some - 요소들 중 하나라도 true를 반환하는가 여부를 반환하는 메서드
  • every - 모든 요소가 true를 반환하는가 여부를 반환하는 메서드

인자들 :

  • 콘백함수 - 인자 : (현재 값, 현재 값의 인덱스, 해당 배열)
  • thisArg
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

console.log(
  arr.some(i => i % 2),
  arr.every(i => i % 2),
  arr.some(i => i < 0),
  arr.every(i => i < 10)
); //true false false true

 

5. filter - 주어진 기준을 충족하는 요소들로 새 배열을 만들어서 반환하는 메서드

원본 배열을 수정하지 않는다.

인자들 : 

  • 콜백함수 - 인자 : (현재 값, 현재 값의 인덱스, 해당 배열)
  • thisArg
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const odds = arr.filter(i => i % 2);
const evens = arr.filter(i => !(i % 2));
const largerThan3 = arr.filter(i => i > 3);

console.log(odds); //[1, 3, 5, 7, 9]
console.log(evens); //[2, 4, 6, 8]
console.log(largerThan3); //[4, 5, 6, 7, 8, 9]

 

6. reduce, reduceRight

주어진 콜백함수에 따라 값들을 접어 나가는 메서드

인자들 :

  • 콜백함수 - 인자 : (이전값, 현재값, 현재 인덱스, 해당 배열)
  • 초기화 값

초기화 값이 없을 때 - 첫 번째와 두 번째 값부터

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

console.log(
  arr.reduce((prev, curr, idx) => {
    console.log(`p: ${prev}, c: ${curr}, i: ${idx}`);
    return prev + curr;
  })
);

출력문은 다음과 같다

이렇게 초기화 값이 없을 때는 현재값 curr에 arr의 두 번째 값인 2가 들어간 것을 알 수 있다. (prev에는 첫 번째 값인 1이 들어갔다). 현재 인덱스 값도 1임을 볼 수 있다.

첫 번째 출력문에서 reduce를 통해 prev + curr 해서 3이 반환되었다. 

두 번째 출력문에서 반환된 3이 prev에 들어갔고 arr에서 2 다음 값인 3이 curr에 대입된 것을 볼 수 있다. 결과는 6반환.

세 번째 출력문에서 6이 prev에, 그리고 arr에서 3 다음 값인 4가 들어갔다.

reduce 메서드는 이런 식으로 콜백함수를 통해 하나하나씩 접어 가는 것을 볼 수 있다.

 

초기화 값이 있을 때의 경우는 다음과 같다

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

console.log(
  arr.reduce((prev, curr, idx) => {
    console.log(`p: ${prev}, c: ${curr}, i: ${idx}`);
    return prev + curr;
  }, 10)
);

초기화 값 10이 들어갔고 인덱스는 0부터 시작한다는 것을 알고 넘어가자.

 

reduceRight는 시작 방향이 오른쪽인 메서드이다.

const arr = ['가', '나', '다', '라', '마', '바', '사'];

console.log(
  arr.reduceRight((prev, curr, idx) => {
    console.log(`p: ${prev}, c: ${curr}, i: ${idx}`);
    return prev + curr;
  })
);

출력문을 확인해보면 알 수 있다.

 

7. sort - 배열을 (주어진 기준대로) 정렬하는 메서드

  • 배열 자체의 순서를 바꾼다 - 원본 수정
  • 해당 배열을 반환한다

인자들 : 

콜백함수 (필수는 아니다) - 인자 : (앞의 값, 뒤의 값)

 

1. 인자가 없을 경우는 다음과 같다

const arr = ['라', '사', '다', '가', '바', '마', '나'];

arr.sort();

console.log(arr); //['가', '나', '다', '라', '마', '바', '사']

인자가 없을 경우 기본적으로 오름차순으로 정렬이 되는 것을 볼 수 있다.

 

let randomWord = 'DBKGICAHFEJ';

console.log(
  randomWord
  .split('')
  .sort()
  .join('')
); //ABCDEFGHIJK

console.log(randomWord); //DBKGICAHFEJ

이번에는 sort를 썼는데도 원본은 바뀌지 않았다.

이유는 split을 사용하면 randomWord가 별도의 배열로 반환되기 때문이다. 그리고 그 배열에다 sort를 했으니 원본은 바뀐것이 없게 되는 것이다. 

 

만약 숫자를 sort하는 경우는 다음과 같다

const arr = [1, 2, 30, 400, 10, 100, 1000];
console.log(arr.sort()); //[1, 10, 100, 1000, 2, 30, 400]

숫자일 경우 오름차순으로 정렬이 되지 않는 것을 볼 수 있다. 

이유는 숫자일 경우 문자열로 암묵적 변환하여 오름차순으로 정렬하기 때문이다. 

 

정확한 정렬을 위해 - 콜백 함수를 사용

  • 두 인자 a와 b: 인접한 두 요소
  • 0보다 큰 값 반환 : b를 앞으로 - 순서 뒤집는다
  • 0 반환 : 순서 유지 - ECMAScript 표준은 아니므로 환경마다 다를 수 있다
  • 0보다 작은 값 반환 : a를 앞으로 - 사실상 순서 유지다

8. flatMap - map 한 다음 flat 매핑해서 펼치는 메서드

인자들 :

  • 콜백함수 - 인자: (현재 값, 현재 값의 인덱스, 해당 배열)
  • thisArg
const arr = [1, 2, 3, 4, 5];

console.log(
  arr.map(i => [i, i, i])
);

그냥 map 매서드를 사용했을 때의 출력문은 다음과 같다

이것을 flat한 것을 flatMap이라고 하는 것이다.

console.log(
  arr.flatMap(i => [i, i, i])
); //(15) [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5]

먼저 map한 결과에 flat이 적용된 것을 볼 수 있다.