기존에 알고있던 개념이 너무 무지성으로 외웠던게 아닌가 싶어서 자바스크립트 쌩기초부터 시작하고 있는데 reduce 함수 사용법을 제대로 몰랐던 것 같아서 블로그에 정리하려고 한다.
예제 1
위 사진을 보면 numbers 라는 변수에 array를 하나 넣었다.
reduce를 실행할 때는 두 개의 파라미터((p, n) => p + n), 0)을 넣었다. 즉, 콜백함수는 첫 번째 파라미터, 초기값은 두 번째 파라미터다.
실행순서를 정리해보면
(1) 초기값인 0이 p에 입력된다.
(2) numbers array의 첫 번째 값인 2가 n에 입력된다.
(3) p + n | 즉, 0(초기값) + 2(첫번째 값)의 결과값인 2가 반환된다.
(4) (3)에서 반환한 값(2)이 p에 입력된다.
(5) array의 두 번째 값인 9가 n에 입력된다.
(6) p + n | 즉, 2 + 9의 결과값인 11이 반환된다.
(7) (6)에서 반환한 값(11)이 p에 입력된다.
(8) numbers 리스트의 모든 값들을 다 순회할 때까지 반복, 결국 모든 값을 다 더한 23이 반환된다.
기본 문법
다른 게시물은 기본 문법을 먼저 적는게 많던데 나는 쉽게 풀어쓴 예제를 먼저 보고 reduce 함수의 형태를 보는게 나을 거 같아 글 뒷부분에 적어보려고 한다. 아래는 위 예시에서 본 reduce 함수의 기본 형태다.
array.reduce(callback[, initialValue])
- array : recude를 적용할 배열
- callback : 배열의 각 요소에 대해 실행할 콜백 함수. 콜백 함수는 다음 매개변수를 가진다.
-> 위 예시에서는 (p, n) => p + n)
- accumulator : 콜백 함수의 반환 값 또는 이전 순회에서의 최종 결과값. 초기 값(initialValue)이 제공된 경우 첫 번째 순회에서는 initialValue로 설정된다.
- currentValue : 현재 순회 중인 배열의 요소
- currentIndex (옵션) : 현재 순회 중인 배열의 요소 인덱트
- array (옵션) : reduce 함수가 호출된 배열
- initialValue (옵션) : 콜백 함수의 첫 번째 순회에서 accumulator로 사용될 초기 값. 초기 값이 제공되지 않으면 배열의 첫 번째 요소가 초기 값이 된다.
-> 위 예시에서는 0을 초기값으로 뒀다.
reduce 함수는 배열을 순회하면서 각 요소에 대해 콜백 함수를 실행시키고, 콜백 함수의 반환 값을 accumulator에 계속해서 누적시킨다. 그리고 순회가 완료되면 accumulator의 최종 값을 반환한다. // 최종값: 23
예제 2
const favourite = [
{
name: '추소정',
age: 30,
job: '아이돌',
married: false,
},
{
name: '남궁민',
age: 47,
job: '배우',
married: true,
},
{
name: '이의리',
age: 23,
job: '야구선수',
married: false,
}
];
// 3명의 나이를 더하는 방법
const sumAge = favourite.reduce((accumulator, currentObject) => {
return accumulator + currentObject.age;
}, 0);
console.log('나이 합 ', sumAge); // 100
작동 방식
예제2에서 초기값을 반드시 넣어 줘야 하는 이유는 reduce의 작동 방식과 관련이 있다.
초기값을 설정했느냐 안했느냐에 따라 콜백함수의 최초 호출 시 accumulator와 currentValue가 달라집니다.
- 초기값 설정 한 경우
callback | accumulator | currentValue | currentIndex |
1번째 호출 | initialValue | 배열의 첫번째 요소 | 0 |
- 초기값을 설정하지 않은 경우
callback | accumulator | currentValue | currentIndex |
1번째 호출 | 배열의 첫번째 요소 | 배열의 두번째 요소 | 1 |
const numbers = [10, 20, 30, 40, 50];
function reducer(accumulator, currentValue, currentIndex) {
const result = accumulator + currentValue;
console.log('accumulator = ', accumulator, ', currentValue = ', currentValue, ', currentIndex = ', currentIndex, ', result = ', result);
return result;
}
// 초기값이 없는 경우
numbers.reduce(reducer);
// 동작
// accumulator = 10, currentValue = 20, currentIndex = 1, result = 30
// accumulator = 30, currentValue = 30, currentIndex = 2, result = 60
// accumulator = 60, currentValue = 40, currentIndex = 3, result = 100
// accumulator = 100, currentValue = 50, currentIndex = 4, result = 150
// 초기값이 있는 경우
numbers.reduce(reducer, 0);
// 동작
// accumulator = 0, currentValue = 10, currentIndex = 0, result = 10
// accumulator = 10, currentValue = 20, currentIndex = 1, result = 30
// accumulator = 30, currentValue = 30, currentIndex = 2, result = 60
// accumulator = 60, currentValue = 40, currentIndex = 3, result = 100
// accumulator = 100, currentValue = 50, currentIndex = 4, result = 150
초기값이 없으면 배열의 2번째부터 계산이 시작되는데 배열이 비어있으면 당연히 TypeError가 발생한다.
배열의 요소가 하나 뿐이면서 초기값이 없는 경우, 또는 초기값은 주어졌으나 배열이 비어 있는 경우엔 계산할 필요가 없기 때문에 그 값을 콜백함수 호출 없이 그대로 반환한다.
위 작동방식을 근거로
예제 2에서 초기값이 없는 경우 첫 번째 콜백에서 TypeError가 발생하게 된다.
const favourite = [
{
name: '추소정',
age: 30,
job: '아이돌',
married: false,
},
{
name: '남궁민',
age: 47,
job: '배우',
married: true,
},
{
name: '이의리',
age: 23,
job: '야구선수',
married: false,
}
];
// 초기값 설정 X
const sumAge = favourite.reduce((accumulator, currentObject) => {
return accumulator + currentObject.age;
});
console.log('나이 합 ', sumAge); // undefined
위 예제에서는 초기값이 없는 reduce 함수를 사용하여 favourite 배열을 순회하려고 시도한다.
그러나 초기값이 없기 때문에 첫 번째 요소가 초기값으로 사용되는데,
첫 번째 요소: { name: '추소정', age: 30, job: '아이돌', married: false }
두 번째 요소: { name: '남궁민', age: 47, job: '배우', married: true }
그러나 리듀서 함수에서는 accumulator와 currentObject.age를 더할 때
accumulator가 객체이고 currentObject.age가 숫자이므로 TypeError가 발생한다.
또한, 초기값이 없는 경우 reduce 함수의 반환 값은 마지막 호출된 리듀서 함수의 반환 값이다.
하지만 위 예제에서는 리듀서 함수가 아무런 값을 반환하지 않기 때문에 sumAge 변수는 undefined가 된다!

'개발.ZIP' 카테고리의 다른 글
[Node.js + Express] Multer Error: Unexpected end of form 해결.ZIP (0) | 2024.08.26 |
---|---|
[React+Typescript] Redux-Persist로 store 저장.ZIP (0) | 2024.01.31 |