Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

joyful

TIP 9: 펼침 연산자로 정렬에 의한 혼란을 피하라 본문

자바스크립트 코딩의 기술

TIP 9: 펼침 연산자로 정렬에 의한 혼란을 피하라

조이풀한 개발자 2023. 11. 4. 11:40

 

배열을 여러번 정렬해도 항상 같은 결과가 나오게 펼침 연산자를 사용할 수 있다. 

이전 Tip들에서 펼침 연산자를 이용해서 여러 가지 조작 함수를 대체하는 방법을 살펴보았다. 

그렇다면 대체하기 쉽지 않은 함수가 있을 때는?

*펼침 연산자로 원본 배열의 사본을 생성하고, 사본을 조작하면 된다. 

 


 

 

예제코드

직원 정보가 담긴 배열을 이름 또는 근속 연수를 기준으로 정렬하는 애플리케이션을 개발한다고 가정해보자.

 

다음은 직원 정보가 담긴 배열이다. 

const staff = [
  {
    name: 'Joe',
    years: 10,
  },
  {
    name: 'Theo',
    years: 5,
  },
  {
    name: 'Dyan',
    years: 10,
  },
];

 

다음으로 이름 또는 근속 연수로 정렬하는 몇 가지 함수를 추가한다. 

function sortByYears(a, b) {
  if (a.years === b.years) {
    return 0;
  }
  return a.years - b.years;
}

const sortByName = (a, b) => {
  if (a.name === b.name) {
    return 0;
  }
  return a.name > b.name ? 1 : -1;
};

 

 

문제

이제 사용자가 열의 제목을 클릭하면 배열에서 정렬(sort) 함수를 호출한다. 

(예, 사용자가 근속 연수에 따라 정렬시키면 함수가 배열을 정렬한다.)

staff.sort(sortByYears);

// [
//   {
//     name: 'Theo',
//     years: 5
//   },
//   {
//     name: 'Joe',
//     years: 10
//   },
//   {
//     name: 'Dyan',
//     years: 10
//   },
// ];

 

여기서 문제가 드러난다.

배열을 정렬할 때 해당 배열의 순서가 변경된다. 

함수 실행이 끝난 것처럼 보일지라도, 실제로 그 배열의 변경 사항이 그대로 저장된다. 

 

 

이번에는 사용자가 이름순으로 정렬한 경우를 보자.

staff.sort(sortByName);

// [
//   {
//     name: 'Dyan',
//     years: 10
//   },
//   {
//     name: 'Joe',
//     years: 10
//   },
//   {
//     name: 'Theo',
//     years: 5
//   },
// ];

역시나 배열의 순서가 변경된다. 

 

만약 사용자가 근속 연수를 기준으로 다시 정렬하면 처음과 전혀 다른 결과가 나온다. 

staff.sort(sortByYears);

// [
//   {
//     name: 'Theo',
//     years: 5
//   },
//   {
//     name: 'Dyan',
//     years: 10
//   },
//   {
//     name: 'Joe',
//     years: 10
//   },
// ]

 

 


 

해결

배열을 정렬하기 전에 원본 배열과 펼침 연산자로 새로운 배열을 만든다. 

원본 배열이 변경되지 않기 때문에 사용자는 마음대로 정렬 기능을 사용할 수 있다. 

[...staff].sort(sortByYears);

// [
//   {
//     name: 'Theo',
//     years: 5
//   },
//   {
//     name: 'Joe',
//     years: 10
//   },
//   {
//     name: 'Dyan',
//     years: 10
//   },
// ];