2015-12-29 18 views
18

Ho una classe ES6 (inclusa con babeljs) con una proprietà getter. Comprendo che queste proprietà non sono enumerabili per impostazione predefinita. Comunque, io non capisco perché io non sono in grado di rendere la proprietà enumerabile utilizzando Object.definePropertyImpostazione di un getter classe ES6 a enumerabile

// 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

+0

Definirlo sull'oggetto prototipo. 'Object.defineProperty (Person.prototype, ...)' – Louy

+0

@Louy stesso plunker con il tuo suggerimento - nessuna modifica: http://plnkr.co/edit/QkQ1JbFEjAAOIFPCtPk7?p=preview – lightswitch05

risposta

26

ES6 getter stile sono definiti sul prototipo, non su ogni singolo person. Per impostare la proprietà greeting per Enumerable è necessario cambiare:

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

A:

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

Object.keys solo rendimenti che gli oggetti propri proprietà enumerabili, così le proprietà sul prototipo non vengono restituiti. Troverete la proprietà greeting in Object.keys(Object.getPrototypeOf(person)) o in un ciclo for...in. Updated Plunker

Se, invece, si desidera che ogni singola istanza di persona per avere il proprio greeting è possibile definire nel costruttore:

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

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

Updated Plunker

+1

Questo funziona, ma wow, non intuitivo o anche logico – lightswitch05

+0

Avrete bisogno di usare il descrittore restituito da 'Object.getOwnPropertyDescriptor (Person.prototype, 'greeting')' altrimenti dovrete * scavalcare * piuttosto che estendere il descrittore 'greeting' e perdete il comportamento' get'. –

+3

@SeanVieira No non è necessario. 'defineProperty' può essere usato per modificare/configurare anche le proprietà esistenti. Finché non specifichi un 'value' o un nuovo' get', l'impostazione enumerable non fermerà il vecchio 'get' dal lavoro. (Si noti nel primo plunker che ho collegato nella mia risposta che 'persona [nome]' restituisce il saluto correttamente). – Paulpro

0

Si può fare trick in questo modo:

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 
    } 
} 

vantaggio è che getter in oggetto pianura sono enumerabili e configurabili per impostazione predefinita, non c'è bisogno di c riguardano questi modificatori ogni volta.

Ma ... sembra un po 'strano) Non so se questo dovrebbe essere veramente usato.