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 8: push() 메서드 대신 펼침 연산자로 원본 변경을 피하라 본문

자바스크립트 코딩의 기술

TIP 8: push() 메서드 대신 펼침 연산자로 원본 변경을 피하라

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

 

push():

  • 새로운 항목을 배열 뒤에 추가해 원본 배열을 변경하는 메서드

 

문제

push()로 인해 발생하는 문제

-다음은 할인 금액을 확인하고 할인 상품이 두 개 이상이면 오류객체를 반환하는 함수이다.
-만약 오류가 없다면 상품을 많이 구매한 사람에게 사은품을 준다.

const cart = [
  {
    name: 'The Foundation Triology',
    price: 19.99,
    discount: false,
  },
  {
    name: 'Godel, Escher, Bach',
    price: 15.99,
    discount: false,
  },
  {
    name: 'Red Mars',
    price: 5.99,
    discount: true,
  },
];

const reward = {
  name: 'Guide to Science Fiction',
  discount: true,
  price: 0,
};

function addFreeGift(cart) { //상품을 많이 구매하면 사은품 증정
  if (cart.length > 2) {
    cart.push(reward);
    return cart;
  }
  return cart;
}

function summarizeCart(cart) {
  const discountable = cart.filter(item => item.discount);
  if (discountable.length > 1) { //할인 상품이 두 개 이상일 경우
    return {
      error: '할인 상품은 하나만 주문할 수 있습니다.',
    };
  }
  const cartWithReward = addFreeGift(cart);
  return {
    discounts: discountable.length,
    items: cartWithReward.length,
    cart: cartWithReward,
  };
}

 

만약 코드를 정리하기 위해 모든 변수를 함수의 상단으로 옮기게 되면 문제가 발생한다. 

addFreeGift가 먼저 호출되어 cart에 reward 객체가 들어가게 돼서, 

할인 상품이(discountable) 2개가 되어 에러 메시지가 뜬다. 

function summarizeCartUpdated(cart) {
  const cartWithReward = addFreeGift(cart);
  const discountable = cart.filter(item => item.discount);
  if (discountable.length > 1) {
    return {
      error: '할인 상품은 하나만 주문할 수 있습니다.',
    };
  }
  return {
    discounts: discountable.length,
    items: cartWithReward.length,
    cart: cartWithReward,
  };
}

-함수 addFreeGift()를 사용하면 push() 메서드로 인해 배열 cart를 조작한다.

-상품이 세 개 이상이면, 할인이 적용된 아이템(free gift)이 추가된다.

-반환값, 즉 장바구니(cart)에 사은품을 추가해 새로운 변수에 할당하더라도, 원본 배열인 cart가 이미 변경된 후이다. 

*결국 상품을 세 가지 이상 선택하고 그 중 하나가 할인 상품인 모든 고객에게 오류가 발생한다. 

 

 

 


해결

spread 연산자를 이용한 해결방법

-기존의 배열을 가져다 대괄호에 펼쳐 넣고, 새로운 상품을 배열의 마지막에 추가한다. 

-내용을 목록으로 다시 쓰기만 하면 되는 것!

-이렇게 되면 새로운 배열을 생성하기 때문에 원본 배열이 변경되지 않는다. 

function addGift(cart) {
  if (cart.length > 2) { //cart에 상품이 2개 이상이면 reward를 배열에 추가
    return [...cart, reward];
  }
  return cart;
}

function summarizeCartSpread(cart) {
  const cartWithReward = addGift(cart);
  const discountable = cart.filter(item => item.discount);
  if (discountable.length > 1) {
    return {
      error: '할인 상품은 하나만 주문할 수 있습니다.',
    };
  }
  return {
    discounts: discountable.length,
    items: cartWithReward.length,
    cart: cartWithReward,
  };
}

 

 

 

slice() 메서드를 이용해 배열의 사본을 만들 수도 있다. 

function forgetting() {]
// 배열의 앞에 추가하기
  const titles = ['Moby Dick', 'White Teeth'];
  titles.shift('The Conscious Mind');

  const moreTitles = ['Moby Dick', 'White Teeth'];
  const evenMoreTitles = ['The Conscious Mind', ...moreTitles];

  // 복사하기
  const toCopy = ['Moby Dick', 'White Teeth'];
  const copied = toCopy.slice();

  const moreCopies = ['Moby Dick', 'White Teeth'];
  const moreCopied = [...moreCopies];
}