Я пытаюсь написать простой объект с геттерами и сеттерами, я не совсем уверен, правильный ли код для этого, я также немного запутался в экземплярах, в которых нужно использовать подчеркивание. Текущая ошибка, которую я получаю, - это menu.addDishToCourses is not a function, но консоль, регистрирующая еду, показывает ее свойство как функцию. Что дает?
let menu = {
_courses: {
_appetizer: [],
_main: [],
_dessert: [],
get appetizers() {
return this._courses.appetizer;
},
set appetizers(appetizerInput) {
this._courses.appetizer = appetizerIn;
},
get mains() {
return this._courses.main;
},
set mains(mainsInput) {
this._courses.main = mainsInput;
},
get desserts() {
return this._courses.dessert;
},
set desserts(dessertsInput) {
this._courses.deseserts = dessertInput;
},
get courses() {
return {
appetizers: this._courses.appetizer,
mains: this._courses.main,
desserts: this._courses.dessert,
};
},
addDishToCourses(courseName, dishName, dishPrice) {
const dish = {
name: dishName,
price: dishPrice,
};
this._courses[courseName].push(dish);
},
getRandomDishFromCourse(courseName) {
const dishes = this._courses[courseName];
const RandomIndex = Math.floor(Math.random() * dishes.length);
return dishes[RandomIndex];
},
generateRandomMeal() {
let appetizer = this.getRandomDishFromCourse('appetizer');
let main = this.getRandomDishFromCourse('main');
let dessert = this.getRandomDishFromCourse('dessert');
let totalPrice = appetizer.price + main.price + dessert.price;
return `You order and appetizer ${appetizer.name},${main.name} and a main dish ${main.price} and a dessert ${dessert.price}. Total price was $${totalProice}. `;
},
}
};
menu.addDishToCourses('_appetizer', 'pepperoni', 5.43);
menu.addDishToCourses('_mains', 'steak', 18.0);
menu.addDishToCourses('_dessert', 'pie', 3.5);
menu имеет одно свойство - _courses. Все остальное определяется как его член, поэтому вам нужно писать menu._courses...... Кроме того, подчеркивание - это соглашение, которое некоторые люди используют для обозначения чего-то частного. Использование этого соглашения не является обязательным. Наконец, чтобы определить метод, вам действительно нужно создать свойство и назначить ему функцию, например: addDishToCourses:function(courseName, dishName, dishPrice){...}.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


У вас проблема с определением объема работ. this в ваших методах получения и установки ссылается на свойство _coursesmenu, а не на сам объект menu.
Вероятно, вы захотите создать свой объект menu, как показано ниже:
let menu = {
_courses: {
_appetizer: [],
_main: [],
_dessert: [],
get appetizer() {
return this._appetizer
},
get main() {
return this._main
},
get dessert() {
return this._dessert
}
},
get courses() {
return {
appetizers: this._courses.appetizer,
main: this._courses.main,
desserts: this._courses.dessert,
};
},
addDishToCourses(courseName, dishName, dishPrice) {
let dish = {
name: dishName,
price: dishPrice,
};
//console.info(this._courses[courseName]);
this._courses[courseName].push(dish);
}
};
menu.addDishToCourses('_appetizer', 'pepperoni', 5.43);
menu.addDishToCourses('_main', 'steak', 18.0);
menu.addDishToCourses('_dessert', 'pie', 3.5);
console.info(menu.courses);Что касается именованных свойств с подчеркиванием, это просто соглашение JavaScript для именования частных переменных (поскольку вы будете обращаться к тем, у которых есть общедоступные методы получения и установки). Подчеркивание на самом деле ничего не делать.
Спасибо, сэр. Подчеркивание сбило меня с толку, теперь я понял.
У menu есть одно свойство: _courses. menu.addDishToCourses() - это не функция, а menu._courses.addDishToCourses() - есть.
Я думаю, вам следует сделать шаг назад и спросить, почему вы используете геттеры и сеттеры, а не просто получаете доступ к свойствам и функциям. Если возникнет необходимость в геттере или сеттере, это должно быть очевидно. Если он станет намного больше, его будет действительно сложно поддерживать.
Сказав это, если вы хотите продолжить работу с текущей схемой, вам просто нужно поместить функции, которые вы хотите вызывать из menu, на menu:
let menu = {
addDishToCourses(courseName, dishName, dishPrice) {
const dish = {
name: dishName,
price: dishPrice,
};
this._courses[courseName].push(dish);
},
get appetizers() {
return this._courses._appetizer;
},
_courses: {
_appetizer: [],
_main: [],
_dessert: [],
}
}
menu.addDishToCourses('_appetizer', 'pepperoni', 5.43);
console.info(menu.appetizers)Ба, ты обогнал меня на несколько секунд, ха-ха. Вероятно, следует отметить, что подчеркивания просто указывают на частные поля / методы и что в этом случае они действительно не нужны?
Несколько быстрых моментов (некоторые из которых были затронуты в различных комментариях):
Подчеркивание - это конфиденциальность соглашение и ничего не делает для обеспечения конфиденциальности. Для пользователей меню это состояние - все еще доступен напрямую.
На мой взгляд, использование геттеров / сеттеров с общедоступными свойствами бесполезно. Назначение геттеров / сеттеров - обеспечить выполнение контракта при доступе к состоянию, чтобы вы могли позже изменить внутренние детали реализации, не затрагивая пользователей вашего модуля. Если они могут напрямую обращаться к вашему состоянию и изменять его, то геттеры / сеттеры просто беспорядок, потому что у вас нет возможности узнать, соблюдают ли пользователи модуля ваши подразумеваемые соглашения о конфиденциальности.
Есть способы сделать ваше состояние приватным в JavaScript (см. Один из вариантов ниже). Однако, если действительно частное состояние не важно, тогда для ясности просто опустите геттеры / сеттеры и подчеркивания. Просто создайте простой объект с некоторыми дополнительными функциями, которые добавляют действительно полезное поведение для управления этим состоянием.
Теперь, если вы действительно хотите сохранить состояние своего меню закрытым и контролировать доступ к нему, вот пример того, как вы могли бы это сделать. Для меня этот подход более понятен, легче читается и действительно выполняет то, что вы планировали.
const menu = (function Menu() {
// this state is privately scoped
const courses = {
appetizers: [],
main: [],
dessert: []
};
// these functions are privately scoped, unless revealed (see below)
function addDish(course, name, price) {
courses[course].push({ name, price });
}
function getDishesByCourse(course) {
return courses[course];
}
// this is what you are revealing to the outside
return { addDish, getDishesByCourse };
})();
menu.addDish('appetizers', 'pepperoni', 5.43);
console.info(menu.getDishesByCourse('appetizers'));
JavaScript совсем не моя сильная сторона, но подчеркивания используются для внутренних свойств, которым сопоставляются ваши геттеры / сеттеры. Еще не изучили подробно, но кажется, что addDishToCourses имеет _courses в качестве родителя, а не меню?