Meal Maker Undefined Help


#1

Hello,

I am having issues with the first project in the JavaScript Objects section.

https://www.codecademy.com/courses/learn-javascript-objects/projects/meal-maker?course_redirect=introduction-to-javascript

I am trying to run the addDishToCourse function which should allow me to add various dishes to the courses object inside of menu object based on the parameters for that function. However when it gets to the part where it should be pushing that information to the appropriate array it comes up as undefined and the property for push fails. Or at least that is what I think is happening. I have gone through the code for a few hours last night and this morning. I have even used debugger; and tried stepping through it but I can not seem to grasp what or why I can not access this. Am I missing a variable being defined, or have I defined them in the wrong place? I thought maybe there was a syntax error and there may be further down but I don’t know for sure.

Any review and help would be greatly appreciated. I am stumped at this point. Thanks

Here is the error I receive from codecademy when saving.

/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:46
    this._courses[courseName].push(dish);
                             ^
TypeError: Cannot read property 'push' of undefined
    at Object.addDishToCourse (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:46:30)
    at Object.<anonymous> (/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:67:6)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:10)
    at run (bootstrap_node.js:427:7)
    at startup (bootstrap_node.js:151:9)
const menu = {
  _courses: {
    _appetizers: [],
    _mains: [],
    _desserts: [],
  
    get appetizers(){
    
    },

    set appetizers(appetizersInput){

    },

    get mains(){

    },

    set mains(mainsInput){

    },

    get desserts(){

    },

    set desserts(dessertsInput){

    }

  },
  
  get courses() {
  	return {
      appetizers: this._courses.appetizers,
      mains: this._courses.appetizers,
      mains: this._courses.desserts
    };
	},
  
  addDishToCourse(courseName, dishName, dishPrice){
  	const dish = {
      name: dishName,
      price: dishPrice
    };
    this._courses[courseName].push(dish);
	},
  
  getRandomDishFromCourse: function (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 `Your meal is ${appetizer.name}, ${main.name}, ${dessert.name}. The price is $${totalPrice}.`;
	}
  
};

//console.log(menu._courses[this.appetizers]);
menu.addDishToCourse('appetizers', 'Cheese Bread', 4.95);
//let meal = menu.generateRandomMeal();
//console.log(meal);
//console.log(menu);


#2

We do not see a setter for this property.

Hopefully I have spoken too soon. Which step are you currently on?


#3

I am currently on step 12. I have been trying to read up on getters/setters more but its a bit hard with distractions around the house today lol. I was wondering if I may have place some of the functions inside or outside of the wrong objects.

Thanks for looking at this.


#6

Still looking through your code. For readability, I would recommend grouping all getters together, and all setters together. Opinion, mind.


#7

That’s definitely a good idea. I grouped them together. I also fixed and issue with this part

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

I could have sworn there was another reply or maybe I was DM’d some code. It didn’t seem to work and I closed the tab out and now can not find it to compare in atom.


#8

This should be an object, not a template string.


#9

Likewise. I don’t see where we are asked to create a setter for courses, but it makes for an interesting addition… The ability to increase the number of courses. Looks a bit tricky…

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set

Scroll down to, ‘Using computed property name’. Will play with this some more when I get time.


#10

I switched that to return dishes[randomIndex]; which I believe is correct. I’t still having fits. I am going to eat, and come back and go line by line and fix any mistakes. I have been tweaking things to little or no effect (at least not any improvements to my current issue).

This is how we learn right? :smiley:


#11

I went through and completed all the requirements with no glitches. If you hit a wall, I can post a spoiler for you to look at.


#12

I was having the same issues with this, I think its where it asks us to make getters and setters for the keys in courses(based off your coding up top) we both left them empty like the hints showed. I took out the getter/setters and it ran fine. if we left those setters empty than that would explain the type issue, if it would lead to undefined maybe?


#13

If they are ever called their returns would be just that.

Spoiler
    set appetizers(appetizer){
      this._appetizers.push(appetizer);
    },
    set mains(entree) {
      this._mains.push(entree);    
    },
    set desserts(dessert) {
      this._desserts.push(dessert);    
    },
    get appetizers() {
      return this._appetizers;
    },
    get mains() {
      return this._mains;
    },
    get desserts() {
      return this._desserts;
    }
  },
  get courses() {
    return {
      appetizers: this._courses.appetizers,
      mains: this._courses.mains,
      desserts: this._courses.desserts,
    };
  },  

#14

So last night I came back late and tried adding return this._appetizers to the get and this._appetizers.push(appetizers); to the set… and nothing. I had the same issue earlier in the day. It was my Aha! moment or so I thought but then everything was blank on Codecamey console. I logged the menu but only got this back and thought well back to the drawing board.

{ _courses: 
   { _appetizers: [ [Object] ],
     _mains: [ [Object] ],
     _desserts: [ [Object] ],
     appetizers: [Getter/Setter],
     mains: [Getter/Setter],
     desserts: [Getter/Setter] },
  courses: [Getter],
  addDishToCourses: [Function: addDishToCourses],
  getRandomDishFromCourse: [Function: getRandomDishFromCourse],
  generateRandomMeal: [Function: generateRandomMeal] }

I’m sure someone probably sees what I was missing but I didn’t yesterday or last night. So then I changed the getter/setters and got an exceeded call stack, shook my fists at the sky and gave up and clicked the spoiler. Again I got the blank screen. So I logged menu in and got the above code and decided to call it a night. This morning I loaded it back up and saw it sitting there clear as day. { _appetizers: [ [Object] ],. When it came up blank it was because I hadn’t console.log anything. When I did I was console logging the wrong thing. As soon as I un-commented my meal variable and the console.log meal it worked.

Thanks again to both of you for helping me find and fix my errors and understanding getters/setters better. Now all is left to round the change to hundredths and all will be right in the world :smiley:


#15
totalPrice.toFixed(2)

#16

:smiley: Yup, Though I ended up using Math.round(). I figure that’s probably what most systems would do using a pos.


#17

Considering we are outputing a string, it makes perfect sense to use .toFixed(2) since it returns a string. No need to dredge up the Math namespace which only wastes memory. .toFixed is a core method.


#18

Nice! I wasn’t aware of the memory usage :slight_smile:


#19

One would need to research this, owing that I’m not well informed of the low level operation of JS. The way I understand it, once we access any one method of the Math module, the entire module (which is its own namespace) moves into memory. That is one assertion to check and verify.

Another understanding I have is that we can import as it were a single method by assigning it.

random = Math.random

I could be totally out in left field for this assumption… random would take on the string representation of the Math.random method. That way it is not a reference to the module, but a reference to a method of the window object. It gets created in the global namespace, so takes up less memory than would the extensive Math module.

To repeat, this needs to be researched and verified, clarified or refuted. I’m looking forward to hear your findings, so do please keep me in the loop. I’ll dig around, not to defend myself. but to track down some reliable sources so we can address other mysteries and misunderstandings that may surface in future.

Personally, I’d rather be wrong than right if it means others will do the follow up to get the facts, to set the record straight. I have always stated that I wish for my statements and assertions to be refuted if they are wrong, clarified if they are vague, or verified if they are correct. Just because I am unsure, does not keep me from writing.


Note that by leaving off the var keyword, we can declare this in any scope, and the variable will belong to window by default.


May not learn anything related to the above, but I did just find a good place to start our reading…

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management


#20

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