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

JS. properties in prototype weird behaviour

本文关键字:属性 原型 JS      更新时间:2023-09-26

我正在努力了解如何在nodejs支持的网络游戏中使属性与原型一起工作。

推理:而不是做类似的事情: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和prototype这是目前的第二个答案。

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

如果您想在不重新定义整个原型对象的情况下使用get方法定义属性,请尝试以下操作:

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

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