JS。原型怪异行为中的属性

时间:2015-12-29 20:56:11

标签: javascript node.js properties prototype

我试图了解如何在nodejs支持的webgame中使属性与原型一起使用。

推理:而不是像Player.attributes.pow.value那样做 它会更容易阅读:Player.pow注意:我不想使用函数,因为Player.pow()让你觉得它不仅仅是返回价值。

因此,为了测试它是如何工作的,我做了一个快速的模型并注意到一个奇怪的行为,虽然它不确定我是否应该这样做:

function Player() {
    this.attributes = { 
    pow: {
      base: 3, 
      value: 3, 
      attChanges: [], 
      multiplier: 0,
      calculateValue: function() {
        var multiplier = this.multiplier;
        var value = 0;
        this.attChanges.forEach( function(att) {
          value += att.value; // For some reason this.value returns NaN in the forEach, this is a way around that...
          multiplier += att.multiplier; 
        });
        this.value = this.base + value;
        this.value *= (1 + multiplier / 100);
      }
    }
  }
  //Change a attribute and calculate it's value
  this.attributes.pow.attChanges.push({value: 3, multiplier: 0});
  this.attributes.pow.calculateValue();
}

Player.prototype.sayHello = function() {
  console.log("hello");
}

Player.prototype = {
    get pow() {
    return this.attributes.pow.value;
    }
}

var p = new Player();

p.sayHello(); // Error
console.log(p.pow);
console.log(p.pow);
p.sayHello();

它说TypeError: p.sayHello is not a function

但如果我把它放在定义属性的下方,它就可以了

Player.prototype = {
    get pow() {
    return this.attributes.pow.value;
    }
}

Player.prototype.sayHello = function() {
  console.log("hello");
}

var p = new Player();

p.sayHello(); // hello 
console.log(p.pow); // 6
console.log(p.pow); // 6
p.sayHello(); // hello

这里发生了什么?这是一个不好的方式吗?我在这里看到了一个例子:JS defineProperty and prototype这是目前的第二个答案。

1 个答案:

答案 0 :(得分:2)

prototype实例变量分配pow时,您正在删除附加sayHello方法的原型的先前定义,因此当您切换声明时,首先进行赋值,然后将实例方法添加到新原型中,以便一切按预期工作。

如果要使用get方法定义属性而不重新定义整个原型对象,请尝试以下方法:

Object.defineProperty(Player.prototype, "pow", {
  get: function() {
    return this.attributes.pow.value;
  }
});

然后,您可以以相对于sayHello声明的任何顺序放置该声明,而不必担心意外的副作用。