FrontEnd/ES&JS 문법

[Javascript] 고차 함수 정리(array, reduce, filter 등)

기은P 2022. 11. 1. 17:59
반응형

1. 개요

고차함수는 외부 상태 변경이나 mutable(가변적인) 데이터를 피하고, 불변성(Immutability)를 지향하는 함수형 프로그래밍에 기반을 두고 있습니다.

함수형 프로그래밍은 순수 함수와 보조 함수의 조합을 통해 로직 내에 존재하는 조건문과 반복문을 제거해 복잡성을 해결하고, 변수의 사용을 억제해 상태 변경을 피하려고 하는 프로그래밍 패러다임 입니다.

-> 조건문이나 반복문은 로직의 흐름을 이해하기 어렵게 해 가독성을 해치고, 변수의 값을 누군가에 의해 언제든지 변경될 수 있어 오류 발생의 근본적인 원인이 될 수 있기 때문입니다.

 

이러한 함수형 프로그래밍은 순수 함수를 통해 side effect를 최대한 억제해 오류를 피하고 프로그램의 안정성을 높이는 방향으로 이어갑니다.

 

 

 

 

2. Array.prototype.sort()

sort는 Timesort 알고리즘을 사용한 순수함수입니다.

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

// ascending(오름차순)
fruits.sort();
console.log(fruits); // [ 'Apple', 'Banana', 'Orange' ]

// descending(내림차순)
fruits.reverse();
console.log(fruits); // [ 'Orange', 'Banana', 'Apple' ]

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

points.sort();
console.log(points); // [ 1, 10, 100, 2, 25, 40, 5 ]

위와 같이 단어, 숫자도 같이 오름순, 내림순으로 정리되며, 이때 원본 배열이 정렬된 배열로 변경됩니다.

 

 

 

 

3. Array.prototype.foreach()

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

// for 문으로 순회
for (let i = 0; i < numbers.length; i++) {
  pows.push(numbers[i] ** 2);
}

console.log(pows); // [ 1, 4, 9 ]

pows = [];

// forEach 메소드로 순회
numbers.forEach(function (item) {
  pows.push(item ** 2);
});

// ES6 화살표 함수
// numbers.forEach(item => pows.push(item ** 2));

console.log(pows); // [ 1, 4, 9 ]

foreach는 배열을 순회해 배열의 각 요소에 대해 인자로 주어진 콜백함수를 실행하는데, 반환값은 undefind입니다.

foreach의 특징은 for문과 다르게 중간에서 break를 할 수 없다는 점입니다.

foreach는 원본 배열(this)를 변경하지 않지만, foreach에서 사용된 콜백 함수 function(item)은 원본 배열을 변경합니다.

 

 

 

 

4. Array.prototype.map()

const numbers = [1, 4, 9];

// 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백함수를 실행
const roots = numbers.map(function (item) {
  // 반환값이 새로운 배열의 요소가 된다. 반환값이 없으면 새로운 배열은 비어 있다.
  return Math.sqrt(item);
});

// 위 코드의 축약표현은 아래와 같다.
// const roots = numbers.map(Math.sqrt);

// map 메소드는 새로운 배열을 반환한다
console.log(roots);   // [ 1, 2, 3 ]
// map 메소드는 원본 배열은 변경하지 않는다
console.log(numbers); // [ 1, 4, 9 ]

map은 배열을 순회해 각 요소에 대해 인자로 주어진 콜백함수의 반환값(결과값)으로 새로운 배열을 생성해 반환합니다.

이때 원본 배열은 변경되지 않습니다.

 

 

 

 

 

5. Array.prototype.filter()

const result = [1, 2, 3, 4, 5].filter(function (item, index, self) {
  console.log(`[${index}] = ${item}`);
  return item % 2; // 홀수만을 필터링한다 (1은 true로 평가된다)
});

console.log(result); // [ 1, 3, 5 ]

filter 메소드를 사용하면 if문을 대체할 수 있습니다.

배열을 순회하며 각 요소에 대해 인자로 주어진 콜백함수의 실행 결과가 true인 요소의 값만을 추출새로운 배열을 반환합니다.

배열에서 특정 케이스만 필터링을 걸어 새로운 배열을 추출할 때 사용합니다.

이때 원본 배열은 변경되지 않습니다.

 

 

 

 

6. Array.prototype.reduce()

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

/*
previousValue: 이전 콜백의 반환값
currentValue : 배열 요소의 값
currentIndex : 인덱스
array        : 메소드를 호출한 배열, 즉 this
*/
// 합산
const sum = arr.reduce(function (previousValue, currentValue, currentIndex, self) {
  console.log(previousValue + '+' + currentValue + '=' + (previousValue + currentValue));
  return previousValue + currentValue; // 결과는 다음 콜백의 첫번째 인자로 전달된다
});

console.log(sum); // 15: 1~5까지의 합
/*
1: 1+2=3
2: 3+3=6
3: 6+4=10
4: 10+5=15
15
*/

// 최대값 취득
const max = arr.reduce(function (pre, cur) {
  return pre > cur ? pre : cur;
});

console.log(max); // 5: 최대값

배열을 순회해 각 요소에 대해 이전의 콜백함수 실행 반환 값을 전달해 콜백함수를 실행하고 그 결과를 반환합니다.

합산, 최소/최대값, 평균 등 계산식에 사용됩니다.

이때 원본 배열은 변경되지 않습니다.

 

const sum = [1, 2, 3, 4, 5].reduce(function (pre, cur) {
  return pre + cur;
}, 5);

console.log(sum); // 20
// 5 + 1 => 6 + 2 => 8 + 3 => 11 + 4 => 15 + 5

reduce는 위와 같이 두번째 파라미터에 초기값을 세팅해서 호출할 수도 있습니다.

 

 

 

 

 

7. Array.prototype.some()

// 배열 내 요소 중 10보다 큰 값이 1개 이상 존재하는지 확인
let res = [2, 5, 8, 1, 4].some(function (item) {
  return item > 10;
});
console.log(res); // false

res = [12, 5, 8, 1, 4].some(function (item) {
  return item > 10;
});
console.log(res); // true

// 배열 내 요소 중 특정 값이 1개 이상 존재하는지 확인
res = ['apple', 'banana', 'mango'].some(function (item) {
  return item === 'banana';
});
console.log(res); // true

배열 내 일부 요소가 콜백함수의 조건을 만족하는지 확인해 그 결과를 boolean 타입으로 반환합니다.

이때 배열의 원본은 변경되지 않습니다.

 

 

 

 

 

8. Array.prototype.every()

// 배열 내 모든 요소가 10보다 큰 값인지 확인
let res = [21, 15, 89, 1, 44].every(function (item) {
  return item > 10;
});
console.log(res); // false

res = [21, 15, 89, 100, 44].every(function (item) {
  return item > 10;
});
console.log(res); // true

배열 내 모든 요소가 콜백함수의 조건을 만족하는지 확인해 그 결과를 boolean 타입으로 반환합니다.

이때 배열의 원본은 변경되지 않습니다.

 

 

 

 

 

9. Array.prototype.find()

const users = [
  { id: 1, name: 'Lee' },
  { id: 2, name: 'Kim' },
  { id: 2, name: 'Choi' },
  { id: 3, name: 'Park' }
];

// 콜백함수를 실행하여 그 결과가 참인 첫번째 요소를 반환한다.
let result = users.find(function (item) {
  return item.id === 2;
});

// ES6
// const result = users.find(item => item.id === 2;);

// Array#find는 배열이 아니라 요소를 반환한다.
console.log(result); // { id: 2, name: 'Kim' }

// Array#filter는 콜백함수의 실행 결과가 true인 배열 요소의 값만을 추출한 새로운 배열을 반환한다.
result = users.filter(function (item) {
  return item.id === 2;
});

console.log(result); // [ { id: 2, name: 'Kim' },{ id: 2, name: 'Choi' } ]

배열을 순회해 각 요소에 대해 인자로 주어진 콜백함수를 실행해, 그 결과가 참인 첫번째 요소를 반환합니다. 만약, 참인 요소가 존재하지 않을 경우 undefined를 반환합니다.

filter와 다른 점은 find는 요소를 반환하는 것이고, filter는 배열을 반환합니다.

 

 

 

9. Array.prototype.findIndex()

const users = [
  { id: 1, name: 'Lee' },
  { id: 2, name: 'Kim' },
  { id: 2, name: 'Choi' },
  { id: 3, name: 'Park' }
];

// 콜백함수를 실행하여 그 결과가 참인 첫번째 요소의 인덱스를 반환한다.
function predicate(key, value) {
  return function (item) {
    return item[key] === value;
  };
}

// id가 2인 요소의 인덱스
let index = users.findIndex(predicate('id', 2));
console.log(index); // 1

// name이 'Park'인 요소의 인덱스
index = users.findIndex(predicate('name', 'Park'));
console.log(index); // 3

배열을 순회해 각 요소에 대해 인자로 주어진 콜백함수를 실행해, 그 결과가 참인 첫번째 요소의 인덱스를 반환합니다. 만약, 참인 요소가 존재하지 않는다면 -1을 반환합니다.

 

 

 

참고 사이트

https://poiemaweb.com/js-array-higher-order-function

 

Higher order function | PoiemaWeb

배열(array)는 1개의 변수에 여러 개의 값을 순차적으로 저장할 때 사용한다. 자바스크립트의 배열은 객체이며 유용한 내장 메소드를 포함하고 있다.

poiemaweb.com

 

반응형