고차함수의 영역에 진입했습니다. 자바스크립트는 함수를 일급 객체로 취급해, 함수를 인자로 받기도 하고 또 함수에서 함수를 리턴할 수 있죠. 변수에 함수를 담는다면 이 변수를 인자로 받거나 리턴하는 것도 가능합니다.
이 때 매개변수 자리에 함수를 인자로 받는 함수를 caller 라고 하고 인자로 전달되는 함수를 callback 함수라고 합니다. callback 함수는 고차함수일수도, 아닐수도 있지만, caller 함수는 고차함수라고 이해할 수 있겠네요.
제목에 적은 배열 메소드 3종 세트인 .map, .filter, .reduce 는 모두 기본적으로 자바스크립트가 내장하고 있는 고차함수입니다. .map 메소드는 배열의 요소들을 함수에 넣어 새로운 요소로 바꾸고, 이를 새로운 배열로 출력해줍니다. .filter 는 배열의 요소들이 함수를 거쳐 걸러지고, 통과된 요소만으로 구성된 새로운 배열을 전달합니다.
.map 과 . filter 가 크게 어렵지 않은 반면 .reduce 는 쉽게 익숙해지지 않아 어려움을 겪었습니다. 그래서 오늘은 .reduce 를 좀 더 집중적으로 정리해볼까 합니다.
개발 공부를 진행하면서 궁금한 것이 있으면 가장 먼저 mdn 문서를 찾아보는 습관을 가지게 되었습니다. .reduce mdn 문서는 .reduce 메소드를 다음과 같이 소개해두었습니다.
reduce() 메서드는 배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.
가장 먼저 이해해야 할 것은 .reduce 메서드는 하나의 결과값을 반환한다는 것입니다. .map 이 배열의 모든 요소들을 함수의 논리에 따라 대응하는 모든 새로운 요소로 치환해주고, .filter 가 함수의 논리에 따라 맞지 않는 요소들을 걸러내고 남은 요소들을 반환한다고 한다면, .reduce 는 함수의 요소들을 뭉쳐서 하나의 결과값을 반환합니다.
(물론 실제로 코드의 작성에 따라 결과물은 다를 수 있습니다. 여기에서는 기본적인 함수의 모습을 이야기하려고 조금 간결하게 표현했습니다.)
.reduce 메소드의 기본 형태는 다음과 같습니다.
const array1 = [1, 2, 3, 4];
const reducer = function (acc, cur) {
return acc + cur;
}
const result = array1.reduce(reducer, 0);
console.log(result); // 10
이 때 reducer 는 callback 함수라고 할 수 있겠네요. .reduce 의 괄호 안에 직접적으로 함수를 만들어줄 수도 있지만, 위처럼 함수를 따로 표현식으로 만들어두고 불러올 수도 있습니다.
.reduce(reducer, 0) 중에서 0 이라고 된 것은 initialValue 입니다. .reduce 메소드가 진행될 때 제공하는 acc 의 초기 값입니다. 이것은 생략이 가능하기 때문에, 생략될 경우에는 배열의 0번째 요소가 첫 번째 acc 가 됩니다.
바로 위 문단이 조금 이해가 어려울 수 있지만, reducer 함수의 매개변수 acc 와 cur 을 이해하다 보면 initialValue 가 무엇을 제공하는지를 바로 알 수 있을 텐데요. 그렇다면 acc 와 cur 은 무엇이냐? acc 는 .reduce 메소드가 반복적으로 진행될 때 그 이전의 return 값이고, cur 은 함수에서 처리하기 위해 배열에서 가져온 현재의 요소 값입니다.
.reduce 메소드를 쉽게 이해하기 위해 우리가 기본적으로 이해하고 있는 반복문의 모양을 빌려오도록 하겠습니다.
const arr = [1, 2, 3, 4];
let result = 0;
for (let i = 0; i < arr.length; i++) {
result = result + arr[i];
}
console.log(result); // 10
.reduce 와 비슷한 방식으로 구동하는 반복문을 작성해봤습니다.(실제로 이렇게 구동하는지 여부는 잘 모르겠습니다 ^^;;)
위의 반복문은 result 라는 변수에 배열 내부의 요소들을 순차적으로 더하여 할당하고 있습니다. .reduce 에는 반복해서 할당하는 부분이 명시적으로 표현되어 있지 않지만, 기능적으로는 같은 결과값이 나타나고 있죠. 생략되었거나 숨겨져있다고 이해하면 될 것 같습니다.
반복문은 배열 내부의 요소만큼 i++ 를 해가며 반복하지만, .reduce 에서는 이 역시 생략되어있습니다. 그럼에도 .reduce 가 실행될 때는 실제로 내부의 요소들을 반복해가며 함수에 따른 결과를 반환하게 되죠.
그렇다면 acc 는 무엇이고 cur 은 무엇일까요? 할당자인 = 오른쪽에 있는 result 는 이전의 반복문에서 반환한 결과를 담고 있죠. 그리고 arr[i] 는 반복문의 진행에 따라 배열에서 현재 진행에 필요한 요소를 담고 있습니다. 따라서 acc 는 result = result + arr[i]; 라는 식에서 할당자인 = 오른쪽의 result 에 해당한다고 할 수 있고, cur 은 arr[i] 에 해당한다고 할 수 있습니다.
// acc == result
// cur == arr[i]
// .reduce == for 반복하며 결과를 result 에 할당
// result = 0 에서 0 == initialValue;
완전하게 일치된다고 말할 수는 없을 것 같아 자바스크립트식 == 연산자를 활용해보았습니다. .reduce 의 개념이 잘 들어오지 않을 때 위와 같은 방식으로도 접근해볼 수 있겠다 정도로 봐주시면 감사하겠습니다.