Meal Maker

Hey Everyone !

I was wondering if i get some help ! I’m pretty stuck on the object Meal Maker Project. For the life of me i don’t know why i am getting this error

/home/ccuser/workspace/learn-javascript-objects-meal-maker/app.js:41
const randomNumber = Math.floor(Math.random() * dishes.length);

  • ^TypeError: Cannot read property ‘length’ of undefined’*

The link to the exercise is :
https://www.codecademy.com/paths/web-development/tracks/web-dev-js-arrays-loops-objects/modules/learn-javascript-objects/projects/meal-maker

My code is :

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) {
return this._courses.appetizers = appetizers;
},
set mains (mains) {
return this._courses.mains = mains;
},
set appetizers (desserts) {
return this._courses.desserts = desserts;
},
get courses () {
return {
appetizers: this.appetizers,
mains: this.mains,
desserts: this.desserts
}
},
addDishToCourse (courseName,dishName,dishPrice) {
const dish = {
name: dishName,
price: dishPrice
};
this._courses[courseName].push(dish);
},
getRandomDishFromCourse(courseName) {
const dishes = this._courses[courseName];
const randomNumber = Math.floor(Math.random() * dishes.length);
return dishes[randomNumber];
},
generateRandomMeal() {
const appetizer = this.getRandomDishFromCourse (this.appetizers);
const mains = this.getRandomDishFromCourse(this.mains);
const desserts = this.getRandomDishFromCourse(this.desserts);
const totalPrice = this.appetizers.price + this.mains.price + this.desserts.price
return Your appetizer is ${appetizers.name}, your mains ${mains.name} and your dessert is ${desserts.name}. The total price is ${totalPrice}
}
};
menu.addDishToCourse (‘appetizers’,‘Shrimp’, 3.50)
menu.addDishToCourse (‘appetizers’,‘Onion Baji’, 3.50)
menu.addDishToCourse (‘appetizers’,‘Wings’, 3.50)
menu.addDishToCourse (‘mains’,‘Burger’, 6.50)
menu.addDishToCourse (‘mains’,‘Rice’, 6.50)
menu.addDishToCourse (‘mains’,‘Salad’, 6.50)
menu.addDishToCourse (‘desserts’,‘Cake’, 3.50)
menu.addDishToCourse (‘desserts’,‘Pudding’, 3.50)
menu.addDishToCourse (‘desserts’,‘MilkShake’, 3.50)

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

1 Like

Hi @py1992920924 - welcome to the forum.

For future posts, please note that formatting your code correctly with the </> option on the ribbon makes it much easier to read. If you click that, then put your code in the middle of the block it generates, like so:

capture_r

then the forum will retain your code layout, rather than ignoring whitespace and screwing up the format. :slight_smile:

Anyway, I think this is what your code actually looks like.
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) {
        return this._courses.appetizers = appetizers;
    },
    set mains(mains) {
        return this._courses.mains = mains;
    },
    set appetizers(desserts) {
        return this._courses.desserts = desserts;
    },
    get courses() {
        return {
            appetizers: this.appetizers,
            mains: this.mains,
            desserts: this.desserts
        }
    },
    addDishToCourse(courseName, dishName, dishPrice) {
        const dish = {
            name: dishName,
            price: dishPrice
        };
        this._courses[courseName].push(dish);
    },
    getRandomDishFromCourse(courseName) {
        const dishes = this._courses[courseName];
        const randomNumber = Math.floor(Math.random() * dishes.length);
        return dishes[randomNumber];
    },
    generateRandomMeal() {
        const appetizer = this.getRandomDishFromCourse(this.appetizers);
        const mains = this.getRandomDishFromCourse(this.mains);
        const desserts = this.getRandomDishFromCourse(this.desserts);
        const totalPrice = this.appetizers.price + this.mains.price + this.desserts.price
        return `Your appetizer is ${ appetizers.name }, your mains ${ mains.name } and your dessert is ${ desserts.name }.The total price is ${ totalPrice }`
}
};
menu.addDishToCourse('appetizers', 'Shrimp', 3.50)
menu.addDishToCourse('appetizers', 'Onion Baji', 3.50)
menu.addDishToCourse('appetizers', 'Wings', 3.50)
menu.addDishToCourse('mains', 'Burger', 6.50)
menu.addDishToCourse('mains', 'Rice', 6.50)
menu.addDishToCourse('mains', 'Salad', 6.50)
menu.addDishToCourse('desserts', 'Cake', 3.50)
menu.addDishToCourse('desserts', 'Pudding', 3.50)
menu.addDishToCourse('desserts', 'MilkShake', 3.50)

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

The error is telling you quite specifically what’s wrong. You’re attempting to do this:
const randomNumber = Math.floor(Math.random() * dishes.length);
but dishes is undefined, and thus does not have a .length property.

If we review the console to get to this point, we can see what’s happening:
image

In your program (which the debugger is referring to as <anonymous> because I’m just running it in the dev tools in Firefox), on line 62 we do this:
const meal = menu.generateRandomMeal()

As we can see from the stack, we’ve jumped to line 45 (inside generateRandomMeal()) to execute const appetizer = this.getRandomDishFromCourse(this.appetizers);.

Once we’re in getRandomDishFromCourse(this.appetizers), we do the following.

  1. Line 40: const dishes = this._courses[courseName];
    Here, we’re looking for an element in _courses which has the name we passed in to the function. Except, the value we’ve passed in is this.appetizers. There’s no such element in _courses{}, so dishes is undefined.

  2. Line 41: const randomNumber = Math.floor(Math.random() * dishes.length);
    Here is where we try and reference a non-existent property .length of the undefined value in dishes. This is the point where the JavaScript interpreter fully falls over, and is the location it directs you to in the error message; however, the problem is not actually here but in the call to getRandomDishFromCourse.

If we pass in "appetizers" instead of this.appetizers, which JS can match to a property in _courses{} - and make the same changes for "mains" and "desserts" as well - we get this*:
Your appetizer is Shrimp, your mains Burger and your dessert is Pudding.The total price is 13.5

* There’s a caveat, which is that I also corrected your totalPrice variable and return statement in generateRandomMeal() because they were also wrong.

Don’t take what I’ve said the wrong way, though - you’re not that far off, I think perhaps you briefly lost track of what some of your methods were expecting as values. Keep in mind also that the location that the interpreter points out to you - in this case line 41 - is not necessarily where the error is or even where the bug originates from. It is, however, usually a good place to start from before working backwards and checking what came before it like I’ve done here.

The following is my adjusted version of your code; all I’ve done is correct the errors. :slight_smile:

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) {
        return this._courses.appetizers = appetizers;
    },
    set mains(mains) {
        return this._courses.mains = mains;
    },
    set appetizers(desserts) {
        return this._courses.desserts = desserts;
    },
    get courses() {
        return {
            appetizers: this.appetizers,
            mains: this.mains,
            desserts: this.desserts
        }
    },
    addDishToCourse(courseName, dishName, dishPrice) {
        const dish = {
            name: dishName,
            price: dishPrice
        };
        this._courses[courseName].push(dish);
    },
    getRandomDishFromCourse(courseName) {
        const dishes = this._courses[courseName];
        const randomNumber = Math.floor(Math.random() * dishes.length);
        return dishes[randomNumber];
    },
    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 appetizer is ${ appetizer.name }, your mains ${ main.name } and your dessert is ${ dessert.name }.The total price is ${ totalPrice }`;
}
};
menu.addDishToCourse('appetizers', 'Shrimp', 3.50)
menu.addDishToCourse('appetizers', 'Onion Baji', 3.50)
menu.addDishToCourse('appetizers', 'Wings', 3.50)
menu.addDishToCourse('mains', 'Burger', 6.50)
menu.addDishToCourse('mains', 'Rice', 6.50)
menu.addDishToCourse('mains', 'Salad', 6.50)
menu.addDishToCourse('desserts', 'Cake', 3.50)
menu.addDishToCourse('desserts', 'Pudding', 3.50)
menu.addDishToCourse('desserts', 'MilkShake', 3.50)

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

Hope that helps, but let us know if you’ve any further questions about the Meal Maker project. :slight_smile:

Not tested, a tiny revision to one of the functions…

generateRandomMeal() {
  const f = this.getRandomDishFromCourse;
  let a, b, c;
  [a, b, c] = [f('appetizers'), f('mains'), f('desserts')];
  return `  Your appetizer is ${a.name}, your main ${b.name} and your dessert is ${c.name}.
  The total price is ${a.price + b.price + c.price}`;
1 Like

Thank you very much for such detailed reply, you’ve taught me what i did wrong and also how to use the debugger to find an error.

1 Like

Thank you for the help !!

1 Like

I stuck to simply fixing errors, rather than refactoring to improve efficiency or similar, but that certainly looks like it would work. :+1:

No problem. :grin: