javascriptarraysclassprototyping

Understanding prototypes and "classes"


Coming from a low level C background, I'm having difficulty understanding this prototype, function constructor, and "classical classing" constructs.

For the purpose of learning, I've tried to design a menu system.

The result should be usable like so:

var testmenu = new menu();
testmenu.addfood("burger");
testmenu.addfood("chips");
testmenu.adddrink("fanta");
testmenu.adddrink("coke");

alert(JSON.stringify(testmenu));

testmenu.foods[0].remove();

alert(JSON.stringify(testmenu));

This is what I came up with:

function menu() {
    var that = this;

    this.foods = new Array();
    this.drinks = new Array();

    this.addfood = function(name) {
        that.foods[that.foods.length] = new food(name);

        // this seems silly, is there a way of getting the index in the array without giving it an index property?
        that.foods[that.foods.length - 1].index = that.foods.length - 1;

        // can't store the menu
        //that.foods[that.foods.length - 1].menu = that;

        return that.foods.length - 1;
    }

    this.adddrink = function(name) {
        that.drinks[that.drinks.length] = new drink(name);

        // same problem as with food
        that.drinks[that.drinks.length - 1].index = that.drinks.length - 1;
        //that.drinks[that.drinks.length - 1].menu = that;

        return that.drinks.length - 1;
    }
}

var menuItem = {
    name: "New menuItem",
    remove: function() {
        alert("Remove: " + this.name + " at index " + this.index);

        // No way of telling what menu the menuItem is in, I have to assume testmenu 
        testmenu[this.menuItemType].splice(this.index, 1);
        //this.menu[this.menuItemType].splice(this.index, 1);
    }
};

function food(name) {
    if(name) this.name = name;
    this.menuItemType = "foods";
}
food.prototype = menuItem;

function drink(name) {
    if(name) this.name = name;
    this.menuItemType = "drinks";
}
drink.prototype = menuItem;

var testmenu = new menu();
testmenu.addfood("burger");
testmenu.addfood("chips");
testmenu.adddrink("fanta");
testmenu.adddrink("coke");

alert(JSON.stringify(testmenu));

testmenu.foods[0].remove();

alert(JSON.stringify(testmenu));

There are two problems I am having:


Solution

  • Your prototypes and "classes" look quite fine.

    there is no way for the remove function to know which menu to remove the menuItem from.

    Sure, how would you know? You might want to pass it as a parameter. However, the more OOP way would be to put the remove method on the menu class (the collection, on which also the add methods are defined) and to pass the item as an argument, instead of having it on the menuitem.

     // can't store the menu
     //that.foods[that.foods.length - 1].menu = that;
    

    What stops you? Sure, JSON.stringify throws an error if you pass in an object with cyclic references. You might want to use a debugger, or at least check the error console. Or try to do console.log(testmenu) instead of the alert, so that you don't need to serialize it but can dynamically inspect it.

    there is no way to get the index of an array item, you have to store it as a property.

    Well, you could search for it using the indexOf array method if you don't want to store the index. It would become inaccurate anyway as soon as you remove other items.