Javascript 使用装饰器将 Class 变量转换为 Getter/Setter
Javascript Convert Class Variable to Getter/Setter using Decorators
关于如何使用装饰器将 class 字段转换为 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
的初始值。
class 需要在存储值的地方保持私有 属性。
由于 class fields aren't currently supported 装饰器提议和较新的 transform-decorators
Babel 插件,应改用较旧的 transform-decorators-legacy
Babel 插件。
如transform-decorators-legacy
documentation 所建议的那样,为了为 属性、initializer
方法和 writable
[= 提供 get/set 访问器46=] 应该从描述符对象中删除。由于 initializer
函数包含初始 class 字段值,因此应将其检索并分配给私有 属性:
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
) 将分配给 class prototype 并且不会触发 set
访问器,而下一个值 (1
) 将分配给 class 实例 并将触发 set
访问器。
由于 transform-decorators-legacy
不符合规范,这不适用于其他装饰器实现,例如TypeScript 和装饰器提案。
上述代码的直接符合 ES6 规范的对应项是:
class Foo {
get bar() { return this._bar };
set bar(val) { this._bar = val };
}
Foo.prototype._bar = 0;
关于如何使用装饰器将 class 字段转换为 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
的初始值。
class 需要在存储值的地方保持私有 属性。
由于 class fields aren't currently supported 装饰器提议和较新的 transform-decorators
Babel 插件,应改用较旧的 transform-decorators-legacy
Babel 插件。
如transform-decorators-legacy
documentation 所建议的那样,为了为 属性、initializer
方法和 writable
[= 提供 get/set 访问器46=] 应该从描述符对象中删除。由于 initializer
函数包含初始 class 字段值,因此应将其检索并分配给私有 属性:
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
) 将分配给 class prototype 并且不会触发 set
访问器,而下一个值 (1
) 将分配给 class 实例 并将触发 set
访问器。
由于 transform-decorators-legacy
不符合规范,这不适用于其他装饰器实现,例如TypeScript 和装饰器提案。
上述代码的直接符合 ES6 规范的对应项是:
class Foo {
get bar() { return this._bar };
set bar(val) { this._bar = val };
}
Foo.prototype._bar = 0;