Confused about Meal Maker project and objects in general

So… I am doing the “Meal Maker” project from the Full-Stack career path’s Learn Javascript Syntax: Objects course.

I went through the material on objects, arrays (even repeated some), etc., but now everything is a mess in my head. I can’t seem to make sense of how all the syntax and methods connect and how to actually use them in practice.

const menu = {
  _courses: {
    _appetizers: [],
    _mains: [],
    _desserts: [],

I understand this code. We need lists where the food types will be stored.

get appetizers() {
      return this._appetizers;
    },
    set appetizers(appetizersIn) {
      this._appetizers = appetizersIn;
    },
    get mains() {
      return this._mains;
    },
    set mains(mainsIn) {
      this._mains = mainsIn;
    },
    get desserts() {
      return this._desserts;
    },
    set desserts(dessertsIn) {
      this._desserts = dessertsIn;
    },
  },

What I don’t understand is why do we need all these getters and setters, why they need to be “returned”, and why do they need to be typed like this?

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

This code also seems redundant to be. If we already have getters and setters, why do we need to get the course properties/keys for another time?

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

I understand that this piece of code is needed to store the type of foods, but why do they need their pwn variable “const dish”? Couldn’t we have combined this code with the “const menu” code and kept everything in one place or am I missing something?

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

I understand that the point of this code is to return a random set of foods. Math.floor and Math.random is something that we have to use a lot in this course, but how does the rest of the code fit in?

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 `Your meal is ${appetizer.name}, ${main.name} and ${dessert.name}. The price is $${totalPrice.toFixed(2)}.`;
  },
};

I understand that this code tries to say that the randomly generated dish is going to be the actual appetizer presented to us. What I don’t understand is the syntax. It makes no sense to me. Seems like a stupid thing to ask.

menu.addDishToCourse('appetizers', 'Ceasar Salad', 4.25);
menu.addDishToCourse('appetizers', 'Prawn Coctail', 4.25);
menu.addDishToCourse('appetizers', 'Garlic Bread', 3.50);

menu.addDishToCourse('mains', 'Lasagna', 9.75);
menu.addDishToCourse('mains', 'Ribeye Steak', 14.95);
menu.addDishToCourse('mains', 'Fish & Chips', 12.95);

menu.addDishToCourse('desserts', 'Cheese Cake', 4.50);
menu.addDishToCourse('desserts', 'Creme Brule', 4.25);
menu.addDishToCourse('desserts', 'Cheese Board', 3.25);

This code is clear - it adds actual appetizers, meals, and desserts to the arrays.

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

This I also understand. It calls for the function so that the meal can be generated for us and prints the result in the console.

i guess I need someone to explain these concepts in layman’s terms since the course materials are not helping me.

You could build the project without getters and setters, that is certainly possible. One of the advantages of getters and setters are that we can directly access the nested property:

const menu = {
   _courses: {
      appetizers: [],
   },
   get appetizers() {
      return this._courses.appetizers;
   }
}

console.log(menu.appetizers);

thanks to the getter, we can get the appetizers property directly (even though its nested within _courses object

each course (appetizers for example) will hold multiple appetizers. Each appetizers is an object containing information about that particular appetizer (name and price). Which is why you create an object here:

     const dish = {
      name: dishName,
      price: dishPrice,
    };

which you append to the course

you could easily console.log() at various stages to see what is actually happening:

const dishes = this._courses[courseName];
console.log(dishes);

so dishes will be all available dishes for that course. From which we then select a random one.

The thing with this exercise, there are some good concepts here. But I understand why they are confusing.

Lets do an example, here:

    _appetizers: [],
    _mains: [],
    _desserts: [],

we could hard-code all the dishes in these array. But in a more real-world application, the dishes would be added by the client (person who wanted the app), so then its nice to have functionality which would enable us to add dishes dynamically (like addDishToCourse does). Ideally, we would also be able to remove dishes

thanks to the getter, we can get the appetizers property directly (even though its nested within _courses object

Oh, so it has to do with how global and block scope works? Because the “_appetizers” is in another block, we need the Getter method so that other functions, blocks can use the same key/parameter?
Is that what the Getter method is mainly for?

you could easily console.log() at various stages to see what is happening:

Omg, you are right! I will try that.

The thing with this exercise, there are some good concepts here. But I understand why they are confusing.

Yeah, I understand that that is the point, which is why the .addDishToCourse was created.

we can do:

const menu = {
   courses: {
      appetizers: [],
   },
}

console.log(menu.courses.appetizers);

which is also possible. But the gettter simplifies the accessing the nested property. This might be a reason to use getters

I also really like the MDN example:

getter - JavaScript | MDN

quite a cool use of getter

good that you can “see” how this might work