未捕获的TypeError:无法设置在第4行只有一个getter的#的属性playerNo

时间:2016-04-11 15:42:34

标签: javascript ecmascript-6

我正在使用旧的(函数和原型)hacky JavaScript类到新的ES6类。

我可能做了些蠢事,但我不确定为什么我不允许这样做:

class Player{
    constructor(playerNo){
        this.playerNo = playerNo;
    }    
    get playerNo(){
        return this.playerNo;
    }

    set cards(playersCards){
        this.cards = playersCards;
    }
    get cards(){
        return this.cards;
    }
}

var steve = new Player(1);

它给了我错误:Uncaught TypeError: Cannot set property playerNo of # which has only a getter on line 4

所以,我尝试了下面的内容:

class Player{
    constructor(playerNo){
        this.playerNo = playerNo;
    }   
    set playerNo(no){
        this.playerNo = no;
    }
    get playerNo(){
        return this.playerNo;
    }

    set cards(playersCards){
        this.cards = playersCards;
    }
    get cards(){
        return this.cards;
    }
}

var steve = new Player(1);

这给了我:Uncaught RangeError: Maximum call stack size exceeded on line 6(这是this.playerNo = no;行)。

有什么想法吗?

3 个答案:

答案 0 :(得分:15)

您通过设置playerNo进行递归。

playerNo设置器中,尝试设置this._playerNo = 0

在其余代码中,继续区分setter方法的名称和存储数据的内部属性。

答案 1 :(得分:2)

您可以将getter用作“受保护”属性的一种,您只能从外部读取它,而没有setter ...

但是,在您的代码中,您试图调用不存在的setter this.playerNo = playerNo,而在getter中,您递归地引用了同一getter return this.playerNo,而不是使用隐藏的this._playerNo属性(在构造函数中相同)-因此出现堆栈溢出错误。

请记住,使用getter / setter时,您需要一些额外的存储空间来实现其价值,例如私有_playerNo属性(除非您将存储空间委派给其他地方)。

答案 2 :(得分:0)

您可能想知道,但在某些用例中,“重新定义 getter”为“具有 fix 值的属性”是意图:

<块引用>

例如实例化一个重对象 按需

  1. 访问 getter 后,我们将其重新定义为属性和值。
  2. 下一次访问只返回属性的值(如缓存...)

let a = 10;
let b = 10;
class Player {
  get clubHistory() {
    return Object.defineProperty(this, 'clubHistory', {
      value: `clubHistory ➜ ${++b}`
    }).clubHistory;
  }

  static get team() {                            // … first ivoce Player.team …
    return Object.defineProperty(this, 'team', { // … re-defines static getter 'team' as property …
      value: `team ➜ ${--a}`                    // … e.g. new Team(..)
    }).team;                                     // … return new value (only relevant for first call)
  }
}

let player1 = new Player();
console.log('player1', player1.clubHistory); // 11 from get
console.log('player1', player1.clubHistory); // 11 from prop

let player2 = new Player();
console.log('player2', player2.clubHistory); // 12 from get
console.log('player2', player2.clubHistory); // 12 from prop

console.log(Player.team); // 9 from static get
console.log(Player.team); // 9 from static prop

console.log('player1', player1.constructor.team); // 9 from static prop
console.log('player2', player2.constructor.team); // 9 from static prop