我是如何使用装饰器将类字段转换为getter / setter的?例如:
class Foo:
@accessor bar = 0;
const foo = new Foo;
应该表现出自定义行为,例如foo.bar = 1;
我已经尝试了类似
的内容function accessor(target, name, descriptor) {
let val;
return {
set: function(newVal) {
val = newVal;
console.log("setter called");
},
get: function() { return val; }
};
}
但是这会丢失bar = 0
的初始值。
答案 0 :(得分:2)
该类需要维护将存储值的私有属性。
由于装饰者提案class fields aren't currently supported以及较新的transform-decorators
Babel插件,应使用较旧的transform-decorators-legacy
Babel插件。
正如transform-decorators-legacy
documentation所示,为了为属性提供get / set访问器,应该从描述符对象中删除initializer
方法和writable
属性。由于initializer
函数包含初始类字段值,因此应检索它并将其分配给私有属性:
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;
由于其工作方式,初始值(0
)将分配给类原型,并且不会触发set
访问器,而下一个值({ {1}})将被分配到类实例,并将触发1
访问者。
由于set
不符合规范,因此这不适用于其他装饰器实现,例如: TypeScript和装饰提案。
上述代码的直接符合规范的ES6对应物是:
transform-decorators-legacy