Установка геттера класса ES6 для перечислимого
У меня есть класс ES6 (transcompiled with babeljs) с свойством getter. Я понимаю, что эти свойства по умолчанию не перечислимы. Однако я не понимаю, почему я не могу сделать свойство перечислимым, используя 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']
Пример плунжера
Ответы
Ответ 1
Геттеры в стиле ES6 определены на прототипе, а не на каждом отдельном person
. Чтобы установить свойство greeting
enumerable, вам нужно изменить:
// Make enumerable (doesn't work)
Object.defineProperty(Person, 'greeting', {enumerable: true});
Для того, чтобы:
// Make enumerable
Object.defineProperty(Person.prototype, 'greeting', {enumerable: true});
Object.keys только возвращает этот объект со своими перечисляемыми свойствами, поэтому свойства прототипа не возвращаются. Свойство greeting
в Object.keys( Object.getPrototypeOf( person ) )
или в цикле for... in. Обновлен Плункер
Если вместо этого вы хотите, чтобы каждый отдельный экземпляр Person имел собственное greeting
вы можете определить его в конструкторе:
class Person {
constructor(myName) {
this.name = myName;
Object.defineProperty( this, 'greeting', {
enumerable: true,
get: function ( ) { return 'Hello, I'm ${this.name}'; }
} );
}
}
Обновлен Плункер
Ответ 2
Вы можете сделать трюк следующим образом:
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
}
}
Преимущество в том, что getters на равном объекте перечислимы и настраиваются по умолчанию, вам не нужно заботиться об этих модификаторах каждый раз.
Но... это выглядит странно) Не уверен, действительно ли это должно быть действительно использовано.
Ответ 3
Что такое класс?
Нестатические методы и методы доступа к классу лежат в прототипе класса, так что каждый его экземпляр наследует их. Вы можете получить к ним доступ через экземпляры, но они не являются собственными свойствами экземпляров. Статические методы и методы доступа лежат на самом классе (который является функцией).
class Test {
#private_field = "A private field.";
public_field = "A public field.";
static get static_getter() {
return "A static getter.";
}
static static_method() {
return "A static method.";
}
get getter() {
return "A non-static getter.";
}
method() {
return "A non-static method.";
}
}
console.log('Class ("${typeof Test}" type)', Object.getOwnPropertyDescriptors(Test));
console.log("Its prototype", Object.getOwnPropertyDescriptors(Test.prototype));
console.log("Its instance", Object.getOwnPropertyDescriptors(new Test));