Meal Maker - this._courses.appetizers is not a function


#1

Hi guys, sorry for posting what probably seems like to you a repeated question, but I’ve spent a lot of frustrated time reading through everyone else’s questions and the answers. I don’t really understand much of this exercise, to be honest, setters and getters don’t really make sense to me.

I’m getting the appetizers is not a function of undefined error for ages… can someone talk me through what I’m doing wrong please?

Note: I’ve not got to calculating the price yet, hence a value just placed in there.

const menu = { //creates an object called menu
  _courses: { //creates a property that is also an object
    _appetizers: [],//set an empty array as a property in _courses
    _mains: [],
    _desserts: [],
    get appetizers() {
    	return this._appetizers;
	  	},
    get mains() {
    	return this._mains;
	  	},
    get desserts() {
    	return this._desserts;
	  	},
    set appetizers(appetizerIn) {
			this._appetizers.push(appetizerIn);
  	  },
    set mains(mainIn) {
      this._mains.push(mainIn);
	    },
    set desserts(dessertIn) {
      this._desserts.push(dessertIn);
    	}
    },
  get courses() {
  	return {
    appetizers: this._courses.appetizers,
    mains: this._courses.mains,
    desserts: this._courses.desserts
    }
  },
  
  addDishToCourse (courseName,dishName,dishPrice) {
		const dish = {
      name: dishName,
      price: dishPrice
    };
    if (courseName === 'appetizers')
    {this._courses.appetizers(dish)} else if (courseName === 'mains') {this._courses.mains(dish)} else if (courseName === 'desserts') {this._courses.desserts(dish)} else {console.log('Course name is invalid.')};
  },
  
  getRandomDishFromCourse (courseName) {
    const dishes = this._courses[courseName];
    const randomIndex = Math.floor(Math.random() * dishes.length);
    return dishes[randomIndex];
  },
  
  generateRandomMeal: function() {
  	const appetizer = this.getRandomDishFromCourse('appetizers');
 		const main = this.getRandomDishFromCourse('mains');
		const dessert = this.getRandomDishFromCourse('desserts');
    const totalPrice = 80;
    return `Your meal starts with ${appetizer} followed by a main of ${main} and finishes with ${dessert}. It comes to a total price of $${totalPrice}.`;
    }
};

menu.addDishToCourse('appetizers','Bruschetta',4.50);
menu.addDishToCourse('appetizers','Quesadillas',5.50);
menu.addDishToCourse('appetizers','Cold Meats',6.50);
//adds three appetizers to the array

menu.addDishToCourse('mains','Pizza',16.50);
menu.addDishToCourse('mains','Steak',22.50);
menu.addDishToCourse('mains','Caviar',29.00);
//adds three mains

menu.addDishToCourse('desserts','Cake',8.00);
menu.addDishToCourse('desserts','Icecream',7.00);
menu.addDishToCourse('desserts','Chocolates',5.00);
//adds three desserts

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

#2

here:

if (courseName === 'appetizers')
    {this._courses.appetizers(dish)} else if (courseName === 'mains') {this._courses.mains(dish)} else if (courseName === 'desserts') {this._courses.desserts(dish)} else {console.log('Course name is invalid.')};

why is this on two lines only? It obscures readability a lot.

i don’t think you understand getters and setters, lets do an example:

const myObj = {
  _someVariable: ['a', 'b', 'c'],
  get someVariable(){
  	return this._someVariable.join(" ")
	},
  set someVariable(input){
    // edit, return shouldn't be used here
    this._someVariable.push(input)
  }
}

console.log(myObj.someVariable);
myObj.someVariable = 'd'
console.log(myObj.someVariable);

we can’t call getters and setters, they are called when we get or set the variable. In my example, i have an array, and i use the getter method to display a nice string instead of the array, and i use the setter method i push to the array, if i didn’t, the array would simple by overwritten with string 'd' (go ahead, try it, remove the setter method, see the difference)

this should also explain why your this._courses.appetizers(dish) isn’t working. appetizers isn’t a function, and we can’t call the setter like that.


#3

Thank you stetime94.

I removed the getter and it console logged ‘a b c’ twice. It wasn’t ‘a b c’ then ‘d’.

So to confirm my understanding:

  • you can’t call a setter or getters directly
  • setters and getters are performed on a variables in an object regardless of whether the property or use of the property explicitly says so
  • setters and getters are used to manipulate properties inside an object, rather than doing it to the property once it’s called

Few more questions…

  1. Why do some of these exercises use getters just to return information, rather than just calling the property itself? They don’t seem to serve any purpose.
  2. Why do you use ‘return’ in the setter?
  3. How do you pass information to a getter, it looks like what you’ve done with myObj.somevariable = ‘d’ is setting a variable. I’ve not seen that before. I think that’s where my confusion is. If I need to pass information to a getter somehow, but it’s not a function, how do I?

Thanks for your help!


#4

exactly. JS handles this for you when we get or set a property

not really, the underscore/low bar indicates we want to use getters and/or setters for the variable, but this is only a naming conventions, JS doesn’t give value to it

well, getter doesn’t manipulate. It just reads the value, that is all.

agree, getters and setters can be useful, but not always, as explained here:

https://stackoverflow.com/questions/34805099/are-getter-and-setter-necessary-in-javascript

In the lesson, the getters aren’t always very valuable. In my example (where i used join) the getter was useful, so then it should be implemented.

good point, i shouldn’t. Because i don’t do much JS at the moment, i am human and i make mistakes. But that you catch it, is for you a good sign :slight_smile: If you can find a mistake, you understand the material :slight_smile:

again, JS is handling a lot of load here. I set someVariable to 'd', now JS will call the setter (if implemented) and pass the value ('d') the the parameter (input) of the setter method

in short, getters and setters are just method we can implement if we want additional control over a property of an object


#5

Thanks for your help, appreciate the clarity! Still my hardest topic to date…


#6

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.