reduce()
메서드는 배열의 각 요소에 대해 주어진 리듀서 (reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.
arr.reduce(callback[, initialValue])
callback 함수의 반환 값은 accumulator에 할당되고 순회중 계속 누적되어 최종적으로 하나의 값을 반환합니다.
최초 callback 함수 실행 시 accumulator 인수에 제공되는 값, 초기값을 제공하지 않을 경우 배열의 첫 번째 요소를 사용하고, 빈 배열에서 초기값이 없을 경우 에러가 발생합니다.
배열을 순서대로 불러 각 요소에 대해 callback 함수를 실행한 결과를 누적한 값
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const sum = numbers.reduce((accumulator, currentNumber) => accumulator + currentNumber);
console.log('sum =', sum);
const list = [
{
id: 0,
value: '국어',
grade: 90,
isCompleted: true
},
{
id: 1,
value: '영어',
grade: 100,
isCompleted: false
},
{
id: 2,
value: '수학',
grade: 60,
isCompleted: false
}
]
// initialValue 설정 X
const totalGrade = list.reduce((accumulator, currentObject) => {
return accumulator + currentObject.grade
}, 0)
console.log('총 점수 :' totalGrade); // 250
예제 2에서 initialValue를 반드시 넣어줘야 하는 이유는 reduce의 작동 방식과 관련이 있습니다.
initialValue를 설정했느냐 안했느냐에 따라 콜백의 최초 호출 시의 accumulator와 currentValue가 달라집니다.
callback | accumulator | currentValue | currentIndex |
---|---|---|---|
1번째 호출 | initialValue | 배열의 첫번째 요소 | 0 |
callback | accumulator | currentValue | currentIndex |
---|---|---|---|
1번째 호출 | 배열의 첫번째 요소 | 배열의 두번째 요소 | 1 |
예를 들어
const number = [1, 2, 3, 4, 5];
function reducer(accumulator, currentValue, currentIndex) {
const result = accumulator + currentValue;
console.log(`accumulator: ${accumulator}, currentValue: ${currentValue}, currentIndex: ${currentIndex}, result: ${result}`);
return result;
}
// initialValue가 없을 경우
number.reduce(reducer);
/*
accumultor: 1, currnetValue: 2, currentIndex: 1, result: 3
accumultor: 3, currnetValue: 3, currentIndex: 2, result: 6
accumultor: 6, currnetValue: 4, currentIndex: 3, result: 10
accumultor: 10, currnetValue: 5, currentIndex: 4, result: 15
*/
// initialValue가 있을 경우
number.reduce(reducer, 0);
/*
accumultor: 0, currnetValue: 1, currentIndex: 0, result: 1
accumultor: 1, currnetValue: 2, currentIndex: 1, result: 3
accumultor: 3, currnetValue: 3, currentIndex: 2, result: 6
accumultor: 6, currnetValue: 4, currentIndex: 3, result: 10
accumultor: 10, currnetValue: 5, currentIndex: 4, result: 15
*/
initialValue가 없으면 배열의 2번째부터 계산이 시작되는데 배열이 비어있으면 당연히 TypeError가 발생합니다.
배열의 요소가 하나 뿐이면서 initialValue가 없는 경우, 또는 initialValue는 주어졌으나 배열이 비어있는 경우엔 계산할 필요가 없기 때문에 그 값을 callback 호출 없이 그대로 반환합니다.
위 작동방식을 근거로
예제 2번의 경우 initialValue가 없을 경우 첫 번째 콜백에서 TypeError가 발생하게 됩니다.
const list = [
{
id: 0,
value: '국어',
grade: 90,
isCompleted: true
},
{
id: 1,
value: '영어',
grade: 100,
isCompleted: false
},
{
id: 2,
value: '수학',
grade: 60,
isCompleted: false
}
]
// initialValue 설정 X
const renderChecked = list.reduce((accumulator, currentObject) => {
return accumulator + currentObject.grade
})
/* 첫번째 콜백 실행 시,
accumulator = {id: 0, value: '국어', grade: 90, isCompleted: true}
currentObject = {id: 01, value: '영어', grade: 100, isCompleted: true}
currentObject.grade = 90
accumulator + currentObject.grade = [Object]90 => typeError
*/
정리 :
reduce()
는 배열의 합을 구하거나, 배열 내 객체 값의 상태를 확인해서 갯수를 세는 데에 사용할 수 있다. (초기값을 설정해주지 않으면 에러 발생 위험이 있으니 주의하자.)