【问题标题】:Uncaught TypeError: Cannot set property playerNo of # which has only a getter on line 4未捕获的类型错误:无法设置属性 playerNo of # 其中只有第 4 行的 getter
【发布时间】:2021-01-24 01:53:19
【问题描述】:

我正在从使用旧的 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; 行)。

有什么想法吗?

【问题讨论】:

  • 你为什么在这里使用getter/setter?你不需要它们。
  • 他们是很好的做法,对吧?此外,我计划很快实现验证,并且没有涉及在很多地方更改代码的设置器。有什么理由不使用它们?
  • 不,当他们不做任何特别的事情时,它们不是好习惯(此外,它们相当慢)。他们只是使代码复杂化。是的,你可以在你实现验证时使用它们,这很好,但你不应该在然后之前使用它们。

标签: javascript ecmascript-6


【解决方案1】:

你有递归设置playerNo

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

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

【讨论】:

  • 知道这会很愚蠢。谢谢。我猜构造函数也可能是constructor(playerNo){ this._playerNo = playerNo; }?还是值得从构造函数调用setter?
  • 我会让构造函数设计直接设置属性。更直接一些,不会将内部属性暴露给公众。
【解决方案2】:

您可以使用 getter 作为“受保护”属性的手段,您只能从外部读取并且它没有 setter ...

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

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

【讨论】:

    【解决方案3】:

    您可能想知道,但在某些用例中,“重新定义 getter”为“property with fix value”是意图:

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

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-02
      • 2021-11-27
      • 1970-01-01
      • 2019-02-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多