Array.prototype.reduce() 메서드는, 자신이 호출한 배열을 모든 요소를 순회하며, 인수로 전달받은 콜백 함수를 반복 호출한다.
라고 딥다이브 책에 쓰여져있지만 사실 이렇게만 보면 직관적으로 확 와닿지 않는다.
배열의 합을 구하는 코드를 한번 구현해보자.
const array = [1, 2, 3, 4];
const sum = array.reduce((acc,cur, index, array) => {
return acc + cur;
}, 0)
console.log(sum); //10
먼저 array.reduce() 안에 들어가는 형식은 array.reduce(콜백함수, 초깃값)이다.
그리고 저 콜백함수를 화살표함수로 표현해주고, 저 화살표 함수 안에 들어가는 인수에는
accmulator(초기값, 또는 콜백함수 이전 반환값), currentValue(현재 값),
index(인덱스), array(reduce 메서드를 호출한 배열 자체, 즉 this)가 전달된다.
더 세밀하게 알아보기 위해서 reduce메서드 안에 인수들의 값을 확인 할수 있도록 콘솔 창을 추가했다.
const array = [1, 2, 3, 4];
const sum = array.reduce((acc, cur, index, array) => {
console.log('acc : ' + acc);
console.log('cur : ' + cur);
return acc + cur;
}, 0)
console.log(sum);
// acc : 1
// cur : 2
// index : 1
// array : 1,2,3,4
// acc : 3
// cur : 3
// index : 2
// array : 1,2,3,4
// acc : 6
// cur : 4
// index : 3
// array : 1,2,3,4
// sum = 10
그리고 reduce 메서드를 사용할때는 항상 초기값을 전달하는것이 안전하다.
빈배열이라던지, 특정 프로퍼티 값을 합산하는 경우에 오류가 날 가능성이 높기 때문이다.
밑의 코드를 살펴보자.
const products = [
{id : 1, price : 100},
{id : 2, price : 200},
{id : 3, prince : 300}
];
const priceSum = products.reduce((acc, cur) => {
console.log('acc : ' + acc);
console.log('cur : ' + cur);
return acc.price + cur.price;
})
console.log(priceSum);
// acc : [object Object]
// cur : [object Object]
// acc : 300
// cur : [object Object]
// NaN
첫번째 순회시 acc 는 {id : 1, price : 100} 이고, cur 은 {id : 2, price : 200}이다.
2번째 순회시 acc는 100과 200이 합쳐진 300이 되고, cur은 {id : 3, prince : 300}이 된다.
이때 300이라는 숫자와 객체가 합쳐져서 NaN이 나오게 된다.
초기값에 0을 넣어보자.
const products = [
{id : 1, price : 100},
{id : 2, price : 200},
{id : 3, price : 300}
];
const priceSum = products.reduce((acc, cur) => {
console.log('acc : ' + acc);
console.log('cur : ' + cur.price);
return acc + cur.price;
}, 0)
console.log(priceSum);
// acc : 0
// cur : 100
// acc : 100
// cur : 200
// acc : 300
// cur : 300
// 600
초가값에 0이 들어가고, cur에는 cur.price이므로 100이라는 숫자가 제대로 나오게 된다.
숫자 + 숫자가 반복되므로 600이라는 값이 제대로 나오게 된다.
이런 문제때문에 reduce메서드를 사용할때는 초기값을 지정해주는 것이 안전하다.