为什么这个方法在sub(sub-sub - ) - document上显示为undefined?

时间:2015-12-12 20:35:23

标签: javascript node.js mongoose

我的架构设置包括一系列嵌套的子文档,如此(从最具体到最常见):

var damageExpressionSchema = new mongoose.Schema({
    /*irrelevant properties*/
});

var effectSchema = new mongoose.Schema({
    damage: [damageExpressionSchema],
    /*irrelevant properties*/
});

var eventSchema = new mongoose.Schema({
    hit: {
        effect: [effectSchema]
    },
    miss: {
        effect: [effectSchema]
    },
    pass: {
        effect: [effectSchema]
    },
    fail: {
        effect: [effectSchema]
    },
    /*irrelevant properties*/
});

var monsterSchema = new Schema({
  actions: [eventSchema],
  /*irrelevant properties*/
});

这些模式中的每一个都包含一个evaluate()方法,该方法应该迭代其嵌套对象并从中返回一些值。在这里的示例中,他们唯一要做的就是记录他们正在开火,然后迭代下来。

damageExpressionSchema.methods.evaluate = function() {
    console.log('damage');
};

effectSchema.methods.evaluate = function() {
    console.log('effect');
    this.damage.forEach(function(damage) {
        damage.evaluate();
    });
};

eventSchema.methods.evaluate = function() {
    console.log('event');
    this.hit.effect.forEach(function(effect) {
        effect.evaluate();
    });
    /*repeat above process for this.miss, this.pass, this.fail*/
};

monsterSchema.methods.evaluate = function () {
    console.log('monster');
    this.actions.forEach(function(action) {
        action.evaluate();
    });
};

所以,给定一个monsterSchema这样的对象:

var clawbutt = new monster({
    "actions": [
        {
          "name": "claws",
          "event": "attack",
          "attackType": "melee",
          "attackSubtype": "weapon",
          "reachRange": 5,
          "attackBonus": 4,
          "hit": {
            "effect": [
              {
                "damage": [
                  {
                    "dice": {
                      "dice": 1,
                      "type": 4,
                      "mod": 3
                    },
                    "type": "piercing"
                  },
                  {
                    "dice": {
                      "dice": 2,
                      "type": 6,
                      "mod": 1
                    },
                    "type": "bludgeoning"
                  }
                ]
              }
            ]
          }
        },
        {
          "name": "claws",
          "event": "attack",
          "attackType": "melee",
          "attackSubtype": "weapon",
          "reachRange": 5,
          "attackBonus": 4,
          "hit": {
            "effect": [
              {
                "damage": [
                  {
                    "dice": {
                      "dice": 1,
                      "type": 4,
                      "mod": 3
                    },
                    "type": "piercing"
                  }
                ]
              }
            ]
          }
        }
    ]
});

...当我呼叫clawbutt.evaluate()时,控制台应记录:

monster
action
effect
damage
damage
action
effect
damage

相反,我收到effect.evaluate不是函数的错误。我知道架构应用于那些效果对象,我知道架构上存在evaluate()方法,但试图在这些效果对象上调用evaluate()错误。无论是以我在这里描述的递归方式调用它还是直接在对象上调用它,如尝试clawbutt.actions[0].hit.effect[0].evaluate(),都会发生这种情况。

这是架构定义方式的问题吗?现在的架构有点乱,因为我正在调整最初使用json-schema的东西到Mongoose中,以便能够更好地扩展它。

1 个答案:

答案 0 :(得分:0)

我设法在comment on a Github问题中找到了这个问题的解决方案,所以对后人来说:

在将子文档架构嵌入另一个架构后,您无法在子文档架构上声明方法。因此,将声明置于不同的顺序使其工作:

var damageExpressionSchema = new mongoose.Schema({
    /*irrelevant properties*/
});

damageExpressionSchema.methods.evaluate = function() {
    console.log('damage');
};

var effectSchema = new mongoose.Schema({
    damage: [damageExpressionSchema],
    /*irrelevant properties*/
});

effectSchema.methods.evaluate = function() {
    console.log('effect');
    this.damage.forEach(function(damage) {
        damage.evaluate();
    });
};

var eventSchema = new mongoose.Schema({
    hit: {
        effect: [effectSchema]
    },
    miss: {
        effect: [effectSchema]
    },
    pass: {
        effect: [effectSchema]
    },
    fail: {
        effect: [effectSchema]
    },
    /*irrelevant properties*/
});

eventSchema.methods.evaluate = function() {
    console.log('event');
    this.hit.effect.forEach(function(effect) {
        console.log('effect', effect);
        effect.evaluate();
    });
    /*repeat above process for this.miss, this.pass, this.fail*/
};

var monsterSchema = new Schema({
  actions: [eventSchema],
  /*irrelevant properties*/
});

monsterSchema.methods.evaluate = function () {
    console.log('monster');
    this.actions.forEach(function(action) {
        action.evaluate();
    });
};