Some questions about 'Meal Maker' project

Hi guys,

Feeling very frustrated with the meal maker project shown here => https://www.codecademy.com/paths/full-stack-engineer-career-path/tracks/fscp-javascript-syntax-part-ii/modules/fecp-learn-javascript-syntax-objects/projects/meal-maker.

Please note I’m quite a n00b so forgive me for the elementary questions, but I really need to fill the gaps in my knowledge.

  1. What is the relevance of adding this into our code?

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

  1. In the above, why do we not use ‘this._courses.appetizers’ - surely that’s how we get to the property?

  2. Please see following code:

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

‘courseName’ hasn’t been defined anywhere previously, so in this line:

this._courses[courseName].push(dish),

Does this push the entered values into a new array called courseName? Having a hard time getting this

  1. How did ‘appetizer’, ‘main’ and ‘dessert’ get linked to the properties of price (name)?

generateRandomMeal() {
const appetizer = this.getRandomDishFromCourse(‘appetizers’);
const main = this.getRandomDishFromCourse(‘mains’);
const dessert = this.getRandomDishFromCourse(‘desserts’);

const totalPrice = appetizer.price + main.price + dessert.price;

I guess it’s related to this earlier step, but I’m baffled.

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

  1. In the final step, why is courseName taken in as a string?

menu.addDishToCourse(‘mains’, ‘curry’, 4.99)

  1. And finally, is this appropriate naming for getter and setter methods? I was confused by the walkthrough as the developer used all the same names.

get appetisers() {
return this._courses.appetizers;
},
get mainz() {
return this._courses.mains;
},
get dessertz() {
return this._courses.desserts;
},
set appetisers(appertiserIn) {
this._courses.appetizers = appertiserIn;
},
set mainz(mainzIn) {
this._courses.mains = mainzIn;
},
set dessertz(dessertzIn) {
this._courses.desserts = dessertzIn;
},

Apologies again for the long and numerous questions, but I’ve been smacking my head against the wall.
Here’s my complete code for reference (it has an error though =/)

const menu = {

_courses: {

appetizers: [],
mains: [],
desserts: []

},

get appetisers() {
return this._courses.appetizers;
},
get mainz() {
return this._courses.mains;
},
get dessertz() {
return this._courses.desserts;
},
set appetisers(appertiserIn) {
this._courses.appetizers = appertiserIn;
},
set mainz(mainzIn) {
this._courses.mains = mainzIn;
},
set dessertz(dessertzIn) {
this._courses.desserts = dessertzIn;
},

// relevance of this???
get courses() {
return {
appetizers: this.appetizers,
mains: this.mains,
dessert: this.desserts // would this work with this._courses.appetizers???
}
},

addDishToCourse(courseName, dishName, dishPrice) {
const dish = {
name: dishName,
price: dishPrice
}
this._courses[courseName].push(dish); // Pushes dish object (with it’s name and price properties) to courses[courseName] - courseName hasn’t been defined, so how does it know where to go? Maybe it’s because the square brackets denote an array

},

// Whenever you see ‘random’, usually involves math.random
getRandomDishFromCourse(courseName) {
const dishes = this._courses[courseName];
const randomI = Math.floor(Math.random() * dishes.length);
// return a dish from dishes using randomI

},

// Will generate a random three course meal
generateRandomMeal() {
const appetizer = this.getRandomDishFromCourse(‘appetizers’);
const main = this.getRandomDishFromCourse(‘mains’);
const dessert = this.getRandomDishFromCourse(‘desserts’);

// How the ■■■■ did appetizer, main, dessert get linked to addDishToCourses?

const totalPrice = appetizer.price + main.price + dessert.price;

return `Your meal is ${appetizer.name}, ${main.name}, and ${dessert.name}, and price is ${totalPrice}`

}

} // closing

menu.addDishToCourse(‘mains’, ‘curry’, 4.99) // why does it take in courseName as a string?
menu.addDishToCourse(‘mains’, ‘kebab’, 4.99)
menu.addDishToCourse(‘mains’, ‘dolma’, 4.99)
menu.addDishToCourse(‘appetizers’, ‘bread’, 1.99)
menu.addDishToCourse(‘appetizers’, ‘pasta dip’, 1.99)
menu.addDishToCourse(‘appetizers’, ‘hummus’, 1.99)
menu.addDishToCourse(‘desserts’, ‘cake’, 2.99)
menu.addDishToCourse(‘desserts’, ‘cream’, 2.99)
menu.addDishToCourse(‘desserts’, ‘kunafa’, 2.99)

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

Thanks!

the courses getter now uses appetizers getter:

get appetisers() {
   return this._courses.appetizers;
},

Now you don’t have to use any of the properties directly, instead, they all rely on the getter

this.appetizers now uses the property created by the getter, which in turn access the property within the courses object

parameter of the method:

addDishToCourse(courseName, dishName, dishPrice)

so now when you call the method:

menu.addDishToCourse(‘mains’, ‘kebab’, 4.99)

the argument ('mains' in this case) is passed along to the courseName parameter.

parameters (like courseName) act as placeholder, until they get a value from the argument provided at method/function call. Actually, we could utilize the getter here:

this[courseName].push(dish);

getRandomDishFromCourse returns an object with two properties:

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

so here:

const appetizer = this.getRandomDishFromCourse(‘appetizers’);

appetizer variable holds an object, you can log the entire object if you want to clarify things for yourself:

const appetizer = this.getRandomDishFromCourse(‘appetizers’);
console.log(appetizer);

as you can see, the object has two properties

yes, this again boils down to parameters and argument. For example:

menu.addDishToCourse(‘mains’, ‘curry’, 4.99) 

we can see the argument for courseName ('mains') is a string

well, you could do something like this:

const example = {
  x: 3,
  get y() {
     return this.x;
  }
}

console.log(example.y);

but this is just confusing. x = y? what?

so instead, we prefix the property with an underscore:

const example = {
  _x: 3,
  get x() {
     return this._x;
  }
}

console.log(example.x);

this is just a naming convention, but now we know _x is used by a getter, and we should not access this property directly.

things become different when we are working with nested objects like in this project, a simplified version of the program:

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

console.log(menu.mains);

as you can, despite the mains property being nested within the _courses object, we can use the getter to access the property directly on menu object, simplifying access.

In javascript, an object is also an associative array and vice versa. This means end up with two notations: the dot/property notation and the associate array notation:

obj.prop // dot notation
obj['prop'] // associative array notation

the dot notation only works when we use the name of the property directly in the code.

we can’t use the dot notation as argument for a function/method call, because then it would be an undefined variable. So we have to pass the argument as string and use the associative array notation

Okay, I hope i covered most. But without doubt you might have further questions. But maybe best to not do to many things at once?

1 Like

Thank you so much stetim! This has helped me clarify some things in my mind, although not 100%.

I will try my best to make sense of this and come back with some follow up questions.

Regards

M

1 Like

Take some time to process it all :slight_smile: Giving yourself time to go through it, might result in new insights. Anything you discover yourself, is generally better then an explanation :slight_smile:

1 Like