JavaScript의 reducer와 sort 직접 구현하며 배운 것들

frontEnd

작성일 : 2024.11.09

최근 캐릭터 리스트 정렬 기능과 결정석 판매 금액을 구현하며 Array.prototype.reduce()와 Array.prototype.sort()를 활용했던
경험을 바탕으로 이 메서드들의 작동 원리를 깊이 이해하기 위해 직접 구현해보았습니다.

reduce() 직접 구현하기

reduce() 함수의 특징으로는 다음이 있습니다.

  • 초기값이 제공되지 않으면 첫 번째 요소를 초기 값으로 사용합니다.
  • 콜백 함수는 누적값(accumulator), 현재값(currentValue), 인덱스(index), 원본 배열(array)을 인자로 받고 있습니다.
  • 원본 배열을 변형하지 않습니다.
function myReduce(arr, callback, initialValue) {
  let accumulator = initialValue !== undefined ? initialValue : arr[0]; // 초기 값이 없을 시 배열의 첫번째 요소 사용
  let startIndex = initialValue !== undefined ? 0 : 1;

  for (let i = startIndex; i < arr.length; i++) {
    accumulator = callback(accumulator, arr[i], i, arr);
  }
  
  return accumulator;
}

// 사용 예시
const sum = myReduce([1, 2, 3], (acc, cur) => acc + cur, 0);
console.log(sum); // 6

결정석 계산 로직

const addPrice = (numbers: number[]): number => {
  return numbers.reduce((sum, current) => sum + current, 0)
}

sort() 직접 구현하기

sort() 함수의 특징으로는 다음이 있습니다.

  • 비교 함수가 제공되지 않으면 유니코드 순으로 정렬합니다.
  • 비교 함수 반환 값이 음수면 a를 b 앞으로, 양수면 뒤로, 0이면 순서를 유지합니다.
  • 원본 배열을 직접 변형하는 특징이 있습니다.
 function mySort(arr, compareFn) { 
  // arr 매개 변수를 사용해 원본 배열을 변형
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i - 1; j++) {
      const comparison = compareFn 
        ? compareFn(arr[j], arr[j + 1])
        : String(arr[j]) > String(arr[j + 1]) ? 1 : -1; // 비교 함수가 없을 때 문자열로 변환 후 정렬
      
      if (comparison > 0) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }
  return arr;
}

// 사용 예시
const characters = [{level: 45}, {level: 23}, {level: 78}];
const sorted = mySort(characters, (a, b) => a.level - b.level);
console.log(sorted); // 레벨 오름차순 정렬

캐릭터 정렬 로직

arr.sort((a, b) => {
  if (a.character_level === b.character_level) {
    return b.final_stat[42].stat_value - a.final_stat[42].stat_value // 전투력 내림차순 정렬
  }
  return b.character_level - a.character_level // 동일 전투력시 레벨  내림차순 정렬
}),

마치며

사용하던 메서드를 직접 구현하며 reducesort이외에도 map, forEach같은 메서드의 공식 문서를 보며 명확한 기능과 사용 방법을 알게 되었고 이런 경험을 통해 단순한 기능 구현뿐 아니라 언어 자체에 대한 이해가 중요하다는 점을 다시 한번 알게 되었습니다.