210814 TIL

코드아카데미 문제 풀이

JAVASCRIPT SYNTAX, PART II - Object

오브젝트에 대한 기초적 개념을 배운 후 활용하는 문제

상황

당신은 새로운 레스토랑에 가보고 다양한 음식을 시도하는 것을 좋아합니다.
그러나 메뉴가 많아 무엇을 먹을지 고민하고 있습니다. 무엇을 먹을지 쉽게 결정 내릴 방법이 없을까요?

문제

마음에 드는 코스요리가 나올 때까지 3개의 식사(appetizer, main, dessert)를 무작위로 출력하세요. 새로고침할 때마다 계속 실행할 수 있습니다.

할 일

  1. 코스 메뉴의 상태와 추가, 랜덤 추출 동작을 하나의 단위로 구조화하기 위해 menu 객체를 생성한다.
  2. courses의 내부 속성 변경을 하면 안된다는 것을 알리기 위해 _courses로 객체 속성을 추가한다.
  3. _courses 객체 안에 각 코스 요리를 담을 수 있도록 appetizers, mains, desserts 이름의 빈 배열을 추가한다.
  4. privacy인 _courses 객체의 속성 안 appetizers, mains 그리고 desserts에 접근하기 위해 getter, setter 메서드를 만든다.
  5. privacy인 _courses에 접근을 위한 getter 메서드를 만든다.
  6. menu객체 내부에 각 코스에 새 요리를 추가할 수 있는 메서드를 만든다.
  7. menu객체 내부에 각 코스에 저장된 요리들을 무작위로 뽑을 수 있는 메서드를 만든다.
  8. 무작위로 뽑은 메뉴들을 모아 메뉴명, 가격이 포함된 문자열을 반환하는 메서드를 만든다.
  9. 8번 메서드를 "meal"이라는 변수에 저장해 출력한다.

menu 객체에 필요한 속성들

  • courses 객체
    - appetizers : 빈 배열
    - mains: 빈 배열
    - desserts: 빈 배열
  • 빈 배열의 메뉴에 추가할 수 있는 함수
  • 배열 안에 있는 메뉴를 랜덤으로 추출할 수 있는 함수
  • 랜덤으로 추출된 메뉴를 합쳐 총 안내말로 출력되는 함수

문제해결

1. menu 객체 생성

const menu = {}

2. menu 객체 내부에 _courses 객체 속성 추가

_courses:{}

왜 '_courses' 인가?
c언어, 자바 등에는 객체에 대한 프라이버시 기능이 내장되어 있지만, 자바스크립트에는 이 기능이 없다. 대신 자바스크립트 다른 개발자에게 알릴 수 있는 명명 규칙이 있는데 일반적인 관례로 속성 이름 앞에 밑줄을 긋는 것으로 속성을 변경해서는 안 된다는 뜻을 담고 있다.

3. appetizers, mains, desserts 빈 배열 추가

_courses:{
  appetizers:[],
  mains:[],
  desserts:[],
}

4. appetizers, mains, desserts에 접근하기 위해 getter, setter 메서드 만들기

get appetizers(){
 return this._courses.appetizers;
},
get mains(){
 return this._courses.mains;
},
get desserts(){
 return this._courses.desserts;
},
set appetizers(appetizers){
 this._courses.appetizers = appetizers;
},
set mains(mains){
 this._courses.mains = mains;
},
set desserts(desserts){
 this._courses.desserts = desserts;
},

왜 setter 메서드에는 return을 쓰지 않을까?
setter도 getter처럼 접근자 함수이기 때문에 return을 쓰지 않으면 반환되는 값이 undefined일 것이라는 예상과 다르게 정상으로 작동하는 출력을 보고 의문을 가졌다. 모던 자바스크립트 책을 읽고 다음과 같은 해답을 찾았다.
getter은 객체의 내부 속성을 가져오고 반환하는 접근자 함수다. 즉, 결과를 반환하기 때문에 return 키워드를 사용한다.
하지만 setter은 객체의 내부 속성값을 재할당 할 수 있다. 즉, 값을 저장하기 때문에 return 키워드가 필요하지 않다.

5. _courses에 접근을 위한 getter 메서드를 만들기

get courses(){
 return {
  appetizers: this.appetizers,
  mains: this.mains,
  desserts: this.desserts,
 }
},

6. 각 코스에 새 요리를 추가할 수 있는 메서드 만들기

 addDishToCourse(courseName,dishName, dishPrice){
    const dish = {
      name: dishName,
      price: dishPrice,
    }
    return this.courses[courseName].push(dish);
  },

7. 각 코스에 저장된 요리들을 무작위로 뽑을 수 있는 메서드 만들기

  getRandomDishFromCourse(courseName){
    const dishes = this.courses[courseName];
    const randomIndex = Math.floor(Math.random() * dishes.length);
    return dishes[randomIndex];
  },

8. 무작위로 뽑은 메뉴들을 모아 메뉴명, 가격이 포함된 문자열을 반환하는 메서드 만들기

  generateRandomMeal(){
    const appetizer =  this.getRandomDishFromCourse('appetizers');
    const main = this.getRandomDishFromCourse('mains');
    const dessert = this.getRandomDishFromCourse('desserts');
    const price = appetizer.price + main.price + dessert.totalPrice;
    return `오늘의 코스를 안내하겠습니다. 에피타이저는 ${appetizer.name}이고 메인요리는 ${main.name}입니다. 식사를 마치면 디저트로 ${dessert.name}를 드리겠습니다. 총 가격은 ${totalPrice}원입니다. 즐거운 식사 되시길 바랍니다.`
  },

9. 8번 메서드를 "meal"이라는 변수에 저장해 출력

menu.addDishToCourse('appetizers', '불고기 샐러드', 12000);
menu.addDishToCourse('appetizers', '연어 샐러드', 14000);
menu.addDishToCourse('appetizers', '야채듬뿍 샐러드', 8000);
menu.addDishToCourse('appetizers', '식전빵 추가', 3000);
menu.addDishToCourse('mains', '한우 스테이크', 38000);
menu.addDishToCourse('mains', '호주산 스테이크', 24000);
menu.addDishToCourse('mains', '쉬림프 로제 파스타', 18000);
menu.addDishToCourse('mains', '불고기 크림 파스타', 18000);
menu.addDishToCourse('mains', '루꼴라 피자', 24000);
menu.addDishToCourse('desserts', '퍼지케이크', 6000);
menu.addDishToCourse('desserts', '아메리카노', 4000);
menu.addDishToCourse('desserts', '뉴욕 치즈케이크', 5500);
menu.addDishToCourse('desserts', '에스프레소', 3500);

let meal = menu.generateRandomMeal();
console.log(meal);
//오늘의 코스를 안내하겠습니다. 에피타이저는 야채듬뿍 샐러드이고 메인요리는 호주산 스테이크입니다. 식사를 마치면 디저트로 아메리카노를 드리겠습니다. 총 가격은 36000원입니다. 즐거운 식사 되시길 바랍니다.

전체코드

const menu = {
  _courses:{
    appetizers:[],
    mains:[],
    desserts:[],
  },
  get appetizers(){
    return this._courses.appetizers;
  },
  get mains(){
    return this._courses.mains;
  },
  get desserts(){
    return this._courses.desserts;
  },
  set appetizers(appetizers){
    this._courses.appetizers = appetizers;
  },
  set mains(mains){
    this._courses.mains = mains;
  },
  set desserts(desserts){
    this._courses.desserts = desserts;
  },
  get courses(){
    return {
      appetizers: this.appetizers,
      mains: this.mains,
      desserts: this.desserts,
    }
  },
  addDishToCourse(courseName,dishName, dishPrice){
    //가격에 '원'을 입력하는 경우가 생겨 추가했다.
    if(typeof dishPrice !== 'number'){
      return console.log('가격은 숫자 입력만 가능합니다');
    }
    const dish = {
      name: dishName,
      price: dishPrice,
    }
    return this.courses[courseName].push(dish);
  },
  getRandomDishFromCourse(courseName){
    const dishes = this.courses[courseName];
    const randomIndex = Math.floor(Math.random() * dishes.length);
    return dishes[randomIndex];
  },
  generateRandomMeal(){
    const appetizer =  this.getRandomDishFromCourse('appetizers');
    const main = this.getRandomDishFromCourse('mains');
    const dessert = this.getRandomDishFromCourse('desserts');
    const totalPrice = appetizer.price + main.price + dessert.price;
    return `오늘의 코스를 안내하겠습니다. 에피타이저는 ${appetizer.name}이고 메인요리는 ${main.name}입니다. 식사를 마치면 디저트로 ${dessert.name}를 드리겠습니다. 총 가격은 ${totalPrice}원입니다. 즐거운 식사 되시길 바랍니다.`
  },
}

menu.addDishToCourse('appetizers', '불고기 샐러드', 12000);
menu.addDishToCourse('appetizers', '연어 샐러드', 14000);
menu.addDishToCourse('appetizers', '야채듬뿍 샐러드', 8000);
menu.addDishToCourse('appetizers', '식전빵 추가', 3000);
menu.addDishToCourse('mains', '한우 스테이크', 38000);
menu.addDishToCourse('mains', '호주산 스테이크', 24000);
menu.addDishToCourse('mains', '쉬림프 로제 파스타', 18000);
menu.addDishToCourse('mains', '불고기 크림 파스타', 18000);
menu.addDishToCourse('mains', '루꼴라 피자', 24000);
menu.addDishToCourse('desserts', '퍼지케이크', 6000);
menu.addDishToCourse('desserts', '아메리카노', 4000);
menu.addDishToCourse('desserts', '뉴욕 치즈케이크', 5500);
menu.addDishToCourse('desserts', '에스프레소', 3500);

let meal = menu.generateRandomMeal();
console.log(meal);

좋은 웹페이지 즐겨찾기