Skip to content

Instantly share code, notes, and snippets.

@dmeehan1968
Created March 5, 2018 15:54
Show Gist options
  • Save dmeehan1968/10e693d763d0f42eafbdadbf252178a9 to your computer and use it in GitHub Desktop.
Save dmeehan1968/10e693d763d0f42eafbdadbf252178a9 to your computer and use it in GitHub Desktop.
ES6 Enumerable Getters on Class Properties

The problem

Getters defined within a class are not enumerable because they are attached to the class prototype. Making them enumerable is not sufficient to have them picked up by Object.keys() or Object.hasOwnProperty() so the values will not usually be exposed without a specific request (object.foo).

The Solution

In the code example, the getter and setter is defined in class scope as expected. A backing variable is defined within the setter, possibly overwriting an existing property if already assigned. This is set to non-enumerable so that it is not exposed to Object.keys().

The getter simply returns the assigned value.

In the constructor, the prototype for the property is copied from the class prototype to the instance, whilst ensuring that instance property is enumerable.

The Refinement

The second code example shows the same thing but with some optimisations to better deal with multiple properties.

class Foo {
set foo(value) {
Object.defineProperty(this, '_foo', {
value: value,
enumerable: false
})
}
get foo() {
return this._foo
}
constructor() {
Object.defineProperty(
this,
'foo',
{
...Object.getOwnPropertyDescriptor(Foo.prototype, 'foo'),
{ enumerable: true }
}
)
}
}
class Foo {
set foo(value) {
Object.defineProperty(this, '_foo', {
value: value,
enumerable: false
})
}
get foo() {
return this._foo
}
set bar(value) {
Object.defineProperty(this, '_bar', {
value: value,
enumerable: false
})
}
get bar() {
return this.bar
}
constructor() {
['foo', 'bar'].forEach(prop => {
Object.defineProperty(
this,
prop,
{
...Object.getOwnPropertyDescriptor(Foo.prototype, prop),
{ enumerable: true }
}
)
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment