Ich versuche, ein einfaches Objekt mit Getter und Setter zu schreiben. Ich bin mir nicht ganz sicher, ob der Code dafür korrekt ist. Ich bin auch etwas verwirrt über die Instanzen, in denen ein Unterstrich verwendet werden soll. Der aktuelle Fehler, den ich erhalte, ist menu.addDishToCourses is not a function, aber die Konsole, die die Mahlzeit protokolliert, zeigt die Eigenschaft davon als Funktion an. Was gibt?

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);
1
user7496931 17 Apr. 2018 im 22:26

3 Antworten

Beste Antwort

Sie haben ein Scoping-Problem. this in Ihren Getter- und Setter-Methoden verweist auf die _courses -Eigenschaft des menu und nicht auf das menu -Objekt selbst.

Sie möchten Ihr menu Objekt wahrscheinlich wie folgt gestalten:

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.log(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.log(menu.courses);

Was die benannten Eigenschaften des Unterstrichs betrifft, handelt es sich lediglich um eine JavaScript-Konvention zum Benennen privater Variablen (da Sie auf solche mit öffentlich zugänglichen Getter- und Setter-Methoden zugreifen). Das Setzen des Unterstrichs macht eigentlich nichts.

0
Tom O. 17 Apr. 2018 im 20:03

Einige kurze Punkte (von denen einige in verschiedenen Kommentaren angesprochen wurden):

  1. Unterstriche sind Datenschutz durch Konvention und tun nichts, um den Datenschutz tatsächlich durchzusetzen. Dieser Status ist für die Menübenutzer immer noch direkt zugänglich .

  2. Die Verwendung von Gettern / Setzern mit öffentlich zugänglichen Eigenschaften ist meiner Meinung nach zwecklos. Der Zweck von Getter / Setter besteht darin, einen Vertrag beim Zugriff auf den Status durchzusetzen, sodass Sie die internen Implementierungsdetails später ändern können, ohne die Benutzer Ihres Moduls zu beeinträchtigen. Wenn sie direkt auf Ihren Status zugreifen und diesen ändern können, sind die Getter / Setter nur unübersichtlich, da Sie nicht wissen können, ob die Modulbenutzer Ihre impliziten Datenschutzkonventionen eingehalten haben.

  3. Es gibt Möglichkeiten, Ihren Status in JavaScript privat zu machen (siehe eine Option unten). Wenn jedoch ein wirklich privater Staat nicht wichtig ist, lassen Sie aus Gründen der Klarheit einfach die Getter / Setter und Unterstriche fallen. Erstellen Sie einfach ein einfaches Objekt mit einigen zusätzlichen Funktionen, die ein wirklich nützliches Verhalten für die Manipulation dieses Zustands hinzufügen.

Wenn Sie Ihren Menüstatus wirklich privat halten und den Zugriff darauf steuern möchten, finden Sie hier ein Beispiel dafür, wie Sie dies tun können. Für mich ist dieser Ansatz sauberer, leichter zu lesen und erreicht tatsächlich das, was Sie beabsichtigt haben.

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.log(menu.getDishesByCourse('appetizers'));
0
ansibly 17 Apr. 2018 im 20:53

Die Art und Weise, wie Sie dieses Setup haben menu, hat eine Eigenschaft: _courses. menu.addDishToCourses() ist keine Funktion, aber menu._courses.addDishToCourses().

Ich denke, Sie sollten einen Schritt zurücktreten und fragen, warum Sie Getter und Setter verwenden, anstatt nur auf Eigenschaften und Funktionen zuzugreifen. Wenn die Notwendigkeit eines Getters oder Setters auftaucht, sollte dies offensichtlich sein. Wenn dies viel größer wird, wird es wirklich schwierig sein, es zu warten.

Wenn Sie jedoch mit dem aktuellen Schema fortfahren möchten, müssen Sie nur die Funktionen, die Sie von menu aufrufen möchten, auf menu setzen:

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.log(menu.appetizers)
1
Mark Meyer 17 Apr. 2018 im 19:42