To meet the requirements of the class, it is necessary to maintain a private property for storing values.
Currently, decorators proposal and newer Babel plugin do not support class fields, so the older transform-decorators-legacy
Babel plugin must be used instead.
According to the transform-decorators-legacy
documentation, in order to provide get/set accessors for a property, the initializer
method and writable
property should be removed from the descriptor object. The initial value from the initializer
function needs to be retrieved and assigned to the private property:
function accessor(classPrototype, prop, descriptor) {
if (descriptor.initializer)
classPrototype['_' + prop] = descriptor.initializer();
delete descriptor.writable;
delete descriptor.initializer;
descriptor.get = function () { return this['_' + prop] };
descriptor.set = function (val) { this['_' + prop] = val };
}
class Foo {
@accessor bar = 0;
}
const foo = new Foo ;
foo.bar = 1;
The initial value (0
) will be assigned to the class prototype and will not trigger the set
accessor, while subsequent values (1
) will be assigned to the class instance and will trigger the set
accessor.
It's important to note that this approach may not work with other decorator implementations like TypeScript and decorator proposal due to the non-spec-compliant nature of transform-decorators-legacy
.
An ES6 equivalent code snippet that is spec-compliant can be written as follows:
class Foo {
get bar() { return this._bar };
set bar(val) { this._bar = val };
}
Foo.prototype._bar = 0;