Javascript 理解原型和;“类”;

Javascript 理解原型和;“类”;,javascript,arrays,class,prototyping,Javascript,Arrays,Class,Prototyping,来自低级C背景,我很难理解这个原型、函数构造函数和“经典分类”结构 为了学习,我尝试设计了一个菜单系统 “menuItem”应具有“name”属性和“remove”函数 “食物”应该基于菜单项,为了简单起见,不应该有自定义属性或功能 “饮料”应该基于menuItem,并且为了简单起见,不应该有自定义属性或函数 “菜单”应包含一系列“食品”、“饮料”和相应的功能,以添加新的“食品”和“饮料” 结果应该是可用的,如下所示: var testmenu = new menu(); testmenu.

来自低级C背景,我很难理解这个原型、函数构造函数和“经典分类”结构

为了学习,我尝试设计了一个菜单系统

  • “menuItem”应具有“name”属性和“remove”函数
  • “食物”应该基于菜单项,为了简单起见,不应该有自定义属性或功能
  • “饮料”应该基于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));
这就是我想到的:

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));
我有两个问题:

  • remove函数无法知道要从哪个菜单中删除菜单项
  • 无法获取数组项的索引,必须将其存储为属性
你的头发看起来很好

remove函数无法知道要从哪个菜单中删除菜单项

当然,你怎么知道?您可能希望将其作为参数传递。但是,更为面向对象的方法是将
remove
方法放在
菜单
类(集合,其中也定义了
add
方法)上,并将该项作为参数传递,而不是将其放在
menuitem

什么阻止了你?当然,如果传入带有循环引用的对象,
JSON.stringify
会抛出错误。您可能希望使用调试器,或者至少检查错误控制台。或者尝试执行
console.log(testmenu)
而不是
警报
,这样您就不需要序列化它,而是可以动态检查它

无法获取数组项的索引,必须将其存储为属性


如果不想存储索引,可以使用。只要删除其他项,它就会变得不准确。

将菜单项放入菜单中的数组,就是在使用合成。当然,除非您在每个项目上创建这样的引用,否则这些项目不会有对菜单的反向引用。如果有反向引用,则需要在数组中搜索要删除的项以获取其索引。在菜单上设置
.remove()
似乎比在每个菜单项上更有意义,因为菜单应该管理自己的状态。然后传递要删除的项目,在数组中找到它,然后删除它。我同意在菜单中而不是在每个菜单项中使用“删除”更有意义。我是JavaScript新手,我尝试用OOP风格来做这件事主要是为了学习,因为我以前从未真正尝试过OOP。还有一件事,如果每个MenuItem都可以获得一些唯一的ID,那么可以使用对象(键/值对)而不是数组来保存单个项。然后,只需
删除这个.foods[food.id]
,其中
这个
是菜单,
食品
是要删除的食品对象。下面是一个需要处理的示例:谢谢,这非常有帮助。
 // can't store the menu
 //that.foods[that.foods.length - 1].menu = that;