【问题标题】:Javascript Convert Class Variable to Getter/Setter using DecoratorsJavascript 使用装饰器将类变量转换为 Getter/Setter
【发布时间】:2018-06-30 05:14:19
【问题描述】:

任何想法如何使用装饰器将类字段转换为 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的初始值。

【问题讨论】:

    标签: javascript babeljs ecmascript-next


    【解决方案1】:

    该类需要维护将存储值的私有属性。

    由于 class fields aren't currently supported by decorators 提议和更新的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) 将分配给类 prototype 并且不会触发 set 访问器,而下一个值 (1) 将被分配到类instance 并会触发set 访问器。

    由于transform-decorators-legacy 不符合规范,这不适用于其他装饰器实现,例如TypeScript 和装饰器提案。

    上述代码的直接符合规范的 ES6 对应物是:

    class Foo {
      get bar() { return this._bar };
      set bar(val) { this._bar = val };
    }
    
    Foo.prototype._bar = 0;
    

    【讨论】:

      猜你喜欢
      • 2017-11-28
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 2021-01-14
      • 1970-01-01
      • 2015-02-28
      相关资源
      最近更新 更多