web-dev-qa-db-fra.com

Définition d'un getter de classe ES6 sur énumérable

J'ai une classe ES6 (transcompilé avec babeljs) avec une propriété getter. Je comprends que ces propriétés ne sont pas énumérables par défaut. Cependant, je ne comprends pas pourquoi je ne parviens pas à rendre la propriété énumérable à l'aide de Object.defineProperty

// Declare class
class Person {
  constructor(myName) {
    this.name = myName;
  }

  get greeting() {
    return `Hello, I'm ${this.name}`;
  }
}

// Make enumerable (doesn't work)
Object.defineProperty(Person, 'greeting', {enumerable: true});

// Create an instance and get enumerable properties
var person = new Person('Billy');
var enumerableProperties = Object.keys(person);
// => ['name']

Exemple Plunker

21
lightswitch05

Les getters de style ES6 sont définis sur le prototype et non sur chaque individu person. Pour définir la propriété greeting sur énumérable, vous devez modifier:

// Make enumerable (doesn't work)
Object.defineProperty(Person, 'greeting', {enumerable: true});

À:

// Make enumerable
Object.defineProperty(Person.prototype, 'greeting', {enumerable: true});

Object.keys ne renvoie que les objets propres propriétés énumérables, les propriétés du prototype ne sont donc pas renvoyées. Vous trouverez la propriété greeting dans Object.keys( Object.getPrototypeOf( person ) ), ou dans un pour ... dans boucle. Plunker mis à jour

Si vous voulez plutôt que chaque instance individuelle de Person ait sa propre greeting, vous pouvez la définir dans le constructeur:

class Person {
  constructor(myName) {
    this.name = myName;

    Object.defineProperty( this, 'greeting', {
      enumerable: true,
      get: function ( ) { return `Hello, I'm ${this.name}`; }
    } );
  }
}

Plunker mis à jour

32
Paulpro

Vous pouvez faire un truc comme ça:

class Person {
  static createFields({ name }) {
    return {
      name,
      get greeting() {
        return `Hello, I'm ${this.name}`;
      }
    }
  }

  constructor(...args) {
    const inst = this.constructor.createFields(...args)
    const desc = Object.getOwnPropertyDescriptors(inst)
    Object.defineProperties(this, desc)
    return this
  }
}

L'avantage est que les accesseurs sur un objet brut sont énumérables et configurables par défaut, vous n'avez pas à vous soucier de ces modificateurs à chaque fois.

Mais ... ça fait un peu bizarre) Je ne sais pas si cela devrait vraiment être utilisé.

0
jeron-diovis