mdn에 나와있는 reduce의 개념은 다음과 같다.
배열의 각 요소에 대해 주어진 리듀서 (reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.
즉, 배열의 요소를 순회하여 reducer 함수를 실행하고, 하나의 결과값을 반환한다. 여기서 말하는 reducer 함수는 reduce 메서드에 인수로 넘긴 함수를 의미한다.
arr.reduce(reducer[, initialValue])
reducer
함수: 각 요소에 대해 실행하는 함수function reducer(accumulator, currentValue, currentIndex, array) {
// ...
return 결과값
}
accumulator
: reducer
의 반환값을 누적한다.currentValue
: 현재 순회하고 있는 요소currentIndex
: 현재 순회하고 있는 요소의 indexarray
: reduce
를 호출한 배열initialValue
: reducer
를 처음으로 호출 할 때 첫 번째 인수로 넘긴 값initialValue
를 제공한 경우, accumulator === initialValue
, currentValue === arr[0]
initialValue
를 제공하지 않은 경우, accumulator === arr[0]
, currentValue === arr[1]
💡 initialValue를 제공하지 않은 경우 reduce는 첫 번째 요소를 건너뛴다.
acc
변수를 선언한다.initialValue
값이 주어진 경우, initialValue
initialValue
값이 주어지지 않은 경우, 배열의 첫 번째 요소배열 순회를 시작할 index를 결정하기 위해 startIdx
변수를 선언한다.
a. initialValue
값이 주어진 경우, 첫 번째 요소부터 순회하므로 0
b. initialValue
값이 주어지지 않은 경우, 첫 번째 요소는 건너뛰기 때문에 1
배열을 startIdx
부터 순회한다.
reducer 함수의 인수로 누적값(acc
), 현재 순회하고 있는 요소(this[idx]
), 순회하고 있는 요소의 index(idx
), 배열(this
)을 넘겨주고, 함수를 실행한다.
함수를 실행한 결과값을 acc
에 재할당한다.
순회를 마치고 나서 누적값(acc
)를 반환한다.
Array.prototype.customReduce = function(reducer, initialValue) {
let acc = initialValue === undefined ? this[0]: initialValue;
let startIdx = initialValue === undefined ? 1 : 0;
console.log(acc,startIdx)
for(let idx = startIdx; idx < this.length; idx++) {
acc = reducer(acc, this[idx], idx, this);
}
return acc;
}
✋ 위 코드에서 this는 어째서 배열을 참조하고 있을까?
답을 알기 위해서 먼저 참조 타입에 대한 개념을 알아야 한다.
객체의 프로퍼티(ex: arr.customReduce
)에 접근하면 참조 타입이라는 값을 반환한다.
(base, name, strict)
arr
)customReduce
)참조 타입 값에 ()
를 붙이면 객체와 메서드에 관련된 모든 정보를 받고, 이 정보를 기반으로 this
가 결정된다.
따라서 점(.
) 또는 대괄호([]
)를 이용해 메서드를 호출했을 때 this
는 참조 타입의 base에 바인딩되어 메서드를 호출한 주체를 가리키게 된다.