Search code examples
javascriptbabeljsecmascript-6

Setting an ES6 class getter to enumerable


I have an ES6 class (transcompiled with babeljs) with a getter property. I understand that these properties are not enumerable by default. However, I do not understand why I am not able to make the property enumerable using 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']

Plunker Example


Solution

  • ES6 style getters are defined on the prototype, not on each individual person. To set the greeting property to enumerable you need to change:

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

    To:

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

    Object.keys only returns that object's own enumerable properties, so properties on the prototype are not returned. You will find the greeting property in Object.keys( Object.getPrototypeOf( person ) ), or in a for...in loop. Updated Plunker

    If instead, you want each individual instance of Person to have its own greeting you can define it in the constructor:

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

    Updated Plunker