【问题标题】:How to disable defining class properties in Babel + transform-decorators-legacy如何禁用在 Babel + transform-decorators-legacy 中定义类属性
【发布时间】:2017-01-09 02:48:06
【问题描述】:

在我的库中(对于 AngularJS),我正在尝试实现以下功能:

  1. 你可以用一些装饰器标记一个空的类属性
  2. 在初始化过程中,这个属性被Object.defineProperty定义的getter替换。
  3. 用户可以在类内部调用该属性,getter会被调用。

但是我在 Babel 中遇到了一个意想不到的行为。在库中使用的 Typescript 中,它运行良好,但是 Babel 创建了一些代码,将已经定义的属性重新定义为它的初始化程序。

是 ES2015 中的装饰类:

@Component({
  selector: 'test'
})
export class TestClass {
  @Inject('$http') $http;
  @Inject('$q') $q;
}

有结果代码:

var TestClass = exports.TestClass = (_dec9 = (0, _ngMetasys.Component)({
  selector: 'test'
}), _dec10 = (0, _ngMetasys.Inject)('$http'), _dec11 = (0, _ngMetasys.Inject)('$q'), _dec9(_class4 = (_class5 = function TestClass() {
  (0, _classCallCheck3.default)(this, TestClass);
  // everything is OK, TestClass.prototype.$http is a getter with function () => $http.

  _initDefineProp(this, '$http', _descriptor5, this); // there are dragons. Property $http is redefined to undefined. 

  _initDefineProp(this, '$q', _descriptor6, this);
}, (_descriptor5 = _applyDecoratedDescriptor(_class5.prototype, '$http', [_dec10], {
  enumerable: true,
  initializer: null
}), _descriptor6 = _applyDecoratedDescriptor(_class5.prototype, '$q', [_dec11], {
  enumerable: true,
  initializer: null
})), _class5)) || _class4);

如何禁用此属性重新定义?有没有办法避免 babel 的属性重新定义或替代它?

【问题讨论】:

    标签: javascript decorator babeljs


    【解决方案1】:

    我想我已经找到了我的问题的答案。 babel-plugin-transform-decorators-legacy 中有一个测试允许设置属性的描述符,甚至可以将简单的属性转换为 getter。

    有一个限制。如果你想记住装饰器稍后更改它,它不会起作用。我没有正确调查它,但我认为我的问题是我在类(和属性)初始化后更改描述符,并且我对描述符所做的更改不会影响已经初始化的属性。

    所以有一个测试给了我提示。来自here

    it('should support mutating an initialzer into an accessor', function(){
      function dec(target, name, descriptor){
        expect(target).to.be.ok;
        expect(name).to.eql("prop");
        expect(descriptor).to.be.an('object');
    
        let {initializer} = descriptor;
        delete descriptor.initializer;
        delete descriptor.writable;
    
        let value;
        descriptor.get = function(){
          if (initializer){
            value = '__' + initializer.call(this) + '__';
            initializer = null;
          }
          return value;
        };
      }
    
      class Example {
        @dec
        prop = 3;
      }
    
      let inst = new Example();
    
      expect(inst.prop).to.eql('__3__');
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-13
      • 1970-01-01
      • 2020-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-18
      相关资源
      最近更新 更多