2015-12-29 2 views
18

Ich habe eine ES6-Klasse (transcompiled mit Babeljs) mit einer Getter-Eigenschaft. Ich verstehe, dass diese Eigenschaften standardmäßig nicht aufzählbar sind. Allerdings verstehe ich nicht, warum ich nicht in der Lage bin die Eigenschaft enumerable mit Object.definePropertyEinstellung eines ES6-Klassengetters auf aufzählbar

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

Definieren Sie es auf dem Prototyp-Objekt. 'Object.defineProperty (Person.prototype, ...)' – Louy

+0

@Louy gleichen Plunder mit Ihrem Vorschlag - keine Änderung: http://plnkr.co/edit/QkQ1JbFEjAAOIFPCtPk7?p=preview – lightswitch05

Antwort

26

ES6 Stil Getter zu machen auf dem Prototyp definiert, nicht auf jedem einzelnen person. Um die greeting Eigenschaft auf zählbare müssen Sie ändern:

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

zu:

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

Object.keys nur Renditen, die eigene enumerable Eigenschaften Objekte, so Eigenschaften auf dem Prototyp werden nicht zurückgegeben. Sie finden die greeting Eigenschaft in Object.keys(Object.getPrototypeOf(person)) oder in einer for...in Schleife. Updated Plunker

Wenn stattdessen möchten, dass Sie jede einzelne Instanz von Person ihre eigenen haben greeting Sie es im Konstruktor definieren:

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

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

Updated Plunker

+1

Dies funktioniert aber wow, nicht intuitiv oder sogar logisch – lightswitch05

+0

Sie müssen den Deskriptor verwenden, der von 'Object.getOwnPropertyDescriptor (Person.prototype, 'gruß') zurückgegeben wird. Andernfalls * überschreiben Sie *, statt den 'Begrüßungsdeskriptor' zu erweitern, und Sie verlieren das 'get'-Verhalten. –

+3

@SeanVieira Nein, du musst nicht. Mit 'defineProperty' können auch bestehende Eigenschaften geändert/konfiguriert werden. Solange Sie keinen "Wert" oder einen neuen "Wert" angeben, wird die Einstellung "Aufzählbar" nicht dazu führen, dass das alte "Get" nicht mehr funktioniert. (Beachten Sie im ersten Fall, dass ich in meiner Antwort verlinkt habe, dass 'person [name]' die Begrüßung korrekt zurückgibt). – Paulpro

0

Sie können wie folgt tun Trick:

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

Vorteil ist, dass Getter auf einfache Objekte sind aufzählbar und konfigurierbar standardmäßig, müssen Sie nicht c sind über diese Modifikatoren jedes Mal.

Aber ... es sieht irgendwie komisch aus) Nicht sicher, ob das wirklich benutzt werden sollte.

Verwandte Themen