hoon's bLog

Javascript 자바스크립트 코딩의 기술 6장 매개변수와 return 문을 정리하라 본문

IT/Javascript

Javascript 자바스크립트 코딩의 기술 6장 매개변수와 return 문을 정리하라

개발한기발자 2024. 2. 15. 11:04
반응형


6장 매개변수와 return 문을 정리하라

tip28. 매개변수 기본값을 생성하라

  • pound를 kilogram으로 변환하는 코드를 보면서 알아보자.(pound를 2.2로 나눠야 kilogram으로 변환)
function convertWeight(weight) {
    return weight / 2.2;
}

 

  • 온스(ounce)도 변환해야 한다는 요구사항이 생겼다.(온스는 1pound === 16ounce 이므로 ounce / 16으로 계산)
function convertWeight(weight, ounces) {
  const oz = ounces ? ounces / 16 : 0;
  const total = weight + oz;
  return total / 2.2;
}

convertWeight(44, 11);
// 20.3125
convertWeight(44, 8);
// 20.227272727272727
convertWeight(6, 9.6);
// 2.9999999999999996
  • convertWeight(6, 9.6); 를 실행하면 3이 나와야 되는데 2.999999...가 나온다.
  • 9.6 / 16 = 0.6이므로 6.6 / 2.2는 3이 되어야 하는데, 3이 나오지 않는 이유는 부동 소수점 연산 때문!!!!!!
    (아래 참고 링크를 통해 부동소수점 참고!)
  • 따라서 반올림을 해야 하므로, 소수점은 2자리까지 표시할 것이다.
function roundToDecimalPlace(number, decimalPlaces) {
  const round = 10 ** decimalPlaces; // decimalPlaces만큼 제곱
  console.log(round);
  console.log(number * round);
  console.log(Math.round(number * round));
  return Math.round(number * round) / round;
}

roundToDecimalPlace(30.8412, 2);
// result
// 100
// 3084.12
// 3084
// 30.84
roundToDecimalPlace(30.8452, 2);
// result
// 100
// 3084.52
// 3085
// 30.85

function convertWeight(weight, ounces, roundTo) {
  const oz = ounces / 16 || 0;
  const total = weight + oz;
  const conversion = total / 2.2;

  const round = roundTo === undefined ? 2 : roundTo;

  return roundToDecimalPlace(conversion, round);
}
  • 위와 같이 코드를 작성하면 잘 동작하지만, 정의되지 않은 변수(매개변수)로 인해 발생하는 삼항 연산자나 단락 평가 때문에 코드가 길어졌다.
  • 이 부분은 매개변수에 기본값을 할당하면 더 효율적이고 가독성이 좋은 코드가 된다.
function convertWeight(weight, ounces = 0, roundTo = 2) {
  const total = weight + ounces / 16;
  const conversion = total / 2.2;

  return roundToDecimalPlace(conversion, roundTo);
}

convertWeight(100, 5, 3);
// 1000
// 45596.590909090904
// 45597
// 45.597

convertWeight(4, 0, 2);
// 100
// 181.8181818181818
// 182
// 1.82

convertWeight(4, null, 2);
// 100
// 181.8181818181818
// 182
// 1.82
  • 매개변수에 타입도 확인 가능하다.
  • 매개변수에 값을 넣으면 해당하는 값에 대한 연산을, 특정 매개변수에 값이 null이라면 coverWeight에 할당된 기본값인 0이 들어가서 연산 됨
  • 하지만, 매개변수 기본값 사용시 단점은 사용하지 않는 매개 변수도 순서대로 입력해야 한다.
  • 이 문제를 해결하기 위해 매개변수로 객체를 전달해야 하는데 이 방법은 다음 팁에서 알아보겠다!!!!

tip29. 해체 할당으로 객체 속성에 접근하라

다음 코드들을 통해 객체와 배열에서 정보를 빠르게 가져오는 방법을 알아보자.

const landscape = {
  title: 'Landscape',
  photographer: 'Nathan',
  equipment: 'Canon',
  format: 'digital',
  src: '/landscape-nm.jpg',
  location: [32.7122222, -103.1405556],
};
  • 위 객체에서 속성들을 특순서에 따라 보여지고 나머지 속성들을 나열하려면?(아래 HTML 코드처럼 반환)
<img alt="Landscape 사진 Nathan 촬영" src="/landscape-nm.jpg" />
<div>Landscape</div>
<div>Nathan</div>
<div>위도: 32.7122222</div>
<div>경도: -103.1405556</div>
<div>
  equipment: Canon <br />
  format: digital
</div>
  • 아래 코드처럼 photo라는 객체를 매개변수로 하고 photo.key 이런식으로 속성에 하나하나 점표기법으로 접근해야 한다.
  • 많은 양의 정보를 다룰 때는 순서를 정할 속성들을 변수로 선언하고, 이 속성들을 객체에서 제거한다.
  • 그리고 나중에 객체를 나열하게되면 모든 정보를 나열할 수 있다.
function displayPhoto(photo) {
  const title = photo.title;
  const photographer = photo.photographer || 'Anonymous';
  const location = photo.location;
  const url = photo.src;

  const copy = { ...photo };
  delete copy.title;
  delete copy.photographer;
  delete copy.location;
  delete copy.src;

  const additional = Object.keys(copy).map((key) => `${key}: ${copy[key]}`);

  return `
    <img alt="${title} 사진 ${photographer} 촬영" src="${url}" />
    <div>${title}</div>
    <div>${photographer}</div>
    <div>위도: ${location[0]} </div>
    <div>경도: ${location[1]} </div>
    <div>${additional.join(' <br/> ')}</div>
  `;
}

물론 이런 방법도 있지만, 객체를 가져오는 수고를 덜기 위해 해체 할당을 해보면 아래 코드와 같다.

const landscape = {
  photographer: 'LEE',
};
const { photographer } = landscape;

console.log(photographer);
// LEE

이런 식으로 원래 코드를 수정해보면 아래와 같다.

function displayPhoto(photo) {
  const {
    title,
    photographer = 'Anonymous',
    location: [latitude, longitude],
    src: url,
    ...other
  } = photo;
  const additional = Object.keys(other).map((key) => `${key}: ${other[key]}`);
  return `
    <img alt="${title} 사진 ${photographer} 촬영" src="${url}" />
    <div>${title}</div>
    <div>${photographer}</div>
    <div>위도: ${latitude} </div>
    <div>경도: ${longitude} </div>
    <div>${additional.join(' <br/> ')}</div>
  `;
}
  • 해체 할당의 가장 큰 장점은 해체 할당을 함수의 매개변수에 적용할 수 있다는 것이다.
  • 대신 매개변수에 적용하게되면 const 대신 let으로 선언하므로 재할당이 가능해진다.
  • 매개변수에 해체 할당을 적용하면 아래 코드와 같다.
function displayPhoto({
  title,
  photographer = 'Anonymous',
  location: [latitude, longitude],
  src: url,
  ...other
}) {
  const additional = Object.keys(other).map((key) => `${key}: ${other[key]}`);
  return `
    <img alt="${title} 사진 ${photographer} 촬영" src="${url}" />
    <div>${title}</div>
    <div>${photographer}</div>
    <div>위도: ${latitude} </div>
    <div>경도: ${longitude} </div>
    <div>${additional.join(' <br/> ')}</div>
  `;
}

사실 처음 사용해보면 다소 복잡하고, 직관성이 떨어져 보일 수 있다.

하지만 사용법에 적응이 된다면 오히려 위 코드가 가독성과 유지 보수 측면에 더 어울릴지도 모르겠다.

(필자는 배운다는 생각으로 보고 있지만, 실무에서는 하나하나 선언하는 타입..)

tip30. 키-값 할당을 단순화하라

const landscape = {
  title: 'Landscape',
  photographer: 'Nathan',
  location: [32.7122222, -103.1405556],
};

function determineCityAndState([latitude, longitude]) {
  // 좌표 탐색을 처리
  const region = {
    city: 'Hobbs',
    county: 'Lea',
    state: {
      name: 'New Mexico',
      abbreviation: 'NM',
    },
  };
  // location정보 기반으로 region을 리턴받았다고 가정.
  return region;    
}

function getCityAndState({ location }) {
  const { city, state } = determineCityAndState(location);
  return {
    city,                       // 위 코드를 통해 받아온 값.
    state: state.abbreviation,  // 전통적인 객체 키-값 선언을 하고 있음에 주의
  };
  // {
  //   city: 'Hobbs',
  //   state: 'NM'
  // }
}

function setRegion({ location, ...details }) { // landscape 객체를 해체할당
  const { city, state } = determineCityAndState(location);
  return {
    city,
    state: state.abbreviation,
    ...details,     // 리턴 값에 주목
  };
}

setRegion(landscape);
// {
//   title: 'Landscape',
//   photographer: 'Nathan',
//   city: 'Hobbs',
//   state: 'NM',
// };
  • 변수와 이름이 같은 키를 갖는 키-값 쌍을 객체에 추가하려면 변수 이름을 적으면 된다
  • 객체 펼침 연산자와 키-값 할당을 함께 사용하여 객체에서 한 가지 정보만 제거 가능!!
    (location을 빼서, 나머지 매개변수를 사용하면 location 정보만 제거)

tip31. 나머지 매개변수로 여러 개의 인수를 변수로 전달하라

  • 나머지 매개변수(rest parameter)를 이용해 개수를 알 수 없는 다수의 매개변수를 전달하는 방법을 살펴보자.
  • 펼침연산자(spread operator)와 매개변수는 반드시 구분해야 한다.
    • 펼침연산자(spread operator) : 배열, 문자열, 객체 등 반복 가능한 객체 (Iterable Object)를 개별 요소로 분리
    • 나머지 매개변수(rest parameter) : 함수가 정해지지 않은 수의 매개변수를 배열로 받을 수 있음!
  • 사진 앱으로 예를 들어보자. 사진 태그의 길이를 일정 수준으로 제한하려고 한다.
  • 아래 코드는 제한 크기, 태그 배열을 매개변수로 받는 함수이다.
function validateCharacterCount(max, items) {
  return items.every((item) => item.length < max);
}

validateCharacterCount(10, ['Hobbs', 'Eagles']);
// true
  • items.length가 max보다 모두 작으면 true를 반환하는 every메서드를 사용한 함수이다.
  • 이 함수의 단점은 items의 컬렉션 형식을 강제한다.(배열) 예를 들어 'Hobbs'대신 ['Hobbs']로 전달해야 한다.
  • 이 문제는 arguments 객체를 이용해 해결할수 있는데 아래 코드와 같다.
function getArguments() {
  return arguments;
}
getArguments('Bloomsday', 'June 16');
// { '0': 'Bloomsday', '1': 'June 16' }

function validateCharacterCount(max) {
  console.log(arguments);
  // Arguments(2) [10, "wvoquie", callee: ƒ, Symbol(Symbol.iterator): ƒ]
  const items = Array.prototype.slice.call(arguments, 1);
  console.log(items);
  // ["wvoquie"]
  return items.every((item) => item.length < max);
}

validateCharacterCount(10, 'wvoquie');
// true

const tags = ['Hobbs', 'Eagles'];
validateCharacterCount(10, ...tags);
// true
  • arguments는 유사배열이므로 배열로 변환한 다음 배열 메서드를 호출!
  • 전달할 변수가 이미 배열이라면 펼침 연산자를 사용(...tags)
  • 물론 이 코드도 작동을 잘 되지만, arguments 객체를 다루기 떄문에 문법이 난해하고, 가독성도 좋지 않다.
  • 나머지 매개변수(rest parameter)를 사용해 개선해보자.
function getArguments(...args) {
  return args;
}
getArguments('Bloomsday', 'June 16');
// ['Bloomsday', 'June 16']

function validateCharacterCount(max, ...items) {
  return items.every((item) => item.length < max);
}

validateCharacterCount(10, 'wvoquie');
// true

validateCharacterCount(10, ...['wvoquie']);
// true

const tags = ['Hobbs', 'Eagles'];
validateCharacterCount(10, ...tags);
// true

// true
validateCharacterCount(10, 'Hobbs', 'Eagles');
  • 단순, 간결해지고 예측가능성이 높아졌다.
  • 함수를 보자마자 최소 2개 이상의 인수를 받을 수 있다는 것을 알 수 있다.
  • 나머지 매개변수를 사용하는 이유
    • 인수를 배열로 다루는 것을 다른 개발자들한테 알리는 경우
    • 추가 매개변수를 가져오는 것으로 추정되는 라이브러리 함수를 해석하는데 도움이 되고 나열된 인수 확인이 가능하여 코드 디버깅에 유리하다.

Reference

 

부동 소수점(Floating Point)란 무엇인가? — Steemit

안녕하세요. 개발자 모도리입니다. 이번에는 잠시 다른 주제를 다뤄 보겠습니다. (EOS Dapp 개발 공부를 못하고 있습니다.) 부동 소수점이란 무엇인가 알아보도록 하겠습니다. 이 주제 선택한 이유

steemit.com

 

나머지 매개변수 - JavaScript | MDN

나머지 매개변수 구문을 사용하면 함수가 정해지지 않은 수의 매개변수를 배열로 받을 수 있습니다. JavaScript에서 가변항 함수를 표현할 때 사용합니다.

developer.mozilla.org

 

728x90
반응형