JavaScript装饰器:将类变量转换为getter/setter

4
有什么办法可以使用装饰器将类字段转换为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的初始值。
1个回答

3
该类要求维护私有属性,在其中存储值。
由于装饰器提案和更新的transform-decorators Babel插件目前不支持类字段, 应改用旧的transform-decorators-legacy Babel插件。
如transform-decorators-legacy 文档所建议的,为了为属性提供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)将被分配给类的实例,并且将触发set访问器。
由于transform-decorators-legacy不符合规范,因此其他装饰器实现(例如TypeScript和装饰器提案)将无法使用此方法。
上面代码的直接符合规范的ES6对应代码是:
class Foo {
  get bar() { return this._bar };
  set bar(val) { this._bar = val };
}

Foo.prototype._bar = 0;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接