Правильное написание геттеров и сеттеров с функцией

Я пытаюсь написать простой объект с геттерами и сеттерами, я не совсем уверен, правильный ли код для этого, я также немного запутался в экземплярах, в которых нужно использовать подчеркивание. Текущая ошибка, которую я получаю, - это 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);

JavaScript совсем не моя сильная сторона, но подчеркивания используются для внутренних свойств, которым сопоставляются ваши геттеры / сеттеры. Еще не изучили подробно, но кажется, что addDishToCourses имеет _courses в качестве родителя, а не меню?

Robert 17.04.2018 21:31
menu имеет одно свойство - _courses. Все остальное определяется как его член, поэтому вам нужно писать menu._courses...... Кроме того, подчеркивание - это соглашение, которое некоторые люди используют для обозначения чего-то частного. Использование этого соглашения не является обязательным. Наконец, чтобы определить метод, вам действительно нужно создать свойство и назначить ему функцию, например: addDishToCourses:function(courseName, dishName, dishPrice){...}.
Scott Marcus 17.04.2018 21:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
103
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

У вас проблема с определением объема работ. 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 для именования частных переменных (поскольку вы будете обращаться к тем, у которых есть общедоступные методы получения и установки). Подчеркивание на самом деле ничего не делать.

Спасибо, сэр. Подчеркивание сбило меня с толку, теперь я понял.

user7496931 17.04.2018 22:54

У 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)

Ба, ты обогнал меня на несколько секунд, ха-ха. Вероятно, следует отметить, что подчеркивания просто указывают на частные поля / методы и что в этом случае они действительно не нужны?

Trasiva 17.04.2018 21:40

Несколько быстрых моментов (некоторые из которых были затронуты в различных комментариях):

  1. Подчеркивание - это конфиденциальность соглашение и ничего не делает для обеспечения конфиденциальности. Для пользователей меню это состояние - все еще доступен напрямую.

  2. На мой взгляд, использование геттеров / сеттеров с общедоступными свойствами бесполезно. Назначение геттеров / сеттеров - обеспечить выполнение контракта при доступе к состоянию, чтобы вы могли позже изменить внутренние детали реализации, не затрагивая пользователей вашего модуля. Если они могут напрямую обращаться к вашему состоянию и изменять его, то геттеры / сеттеры просто беспорядок, потому что у вас нет возможности узнать, соблюдают ли пользователи модуля ваши подразумеваемые соглашения о конфиденциальности.

  3. Есть способы сделать ваше состояние приватным в 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'));

Другие вопросы по теме