Skip to content

Decorator 装饰器语法

1. 背景

如何看待 ECMAScript 装饰器(Decorators)提案进入 stage 3? - 知乎 (zhihu.com)

[2022年06]装饰器 - ECMAScript 6入门 (ruanyifeng.com)

暂定ts5.2支持装饰器第三阶段

「程序猿同事的分享」TypeScript 元数据的理解与使用

ts会预留装饰器的口子

  • "design:type"
  • "design:paramtypes"
  • "design:returntype" 不能隐式推断,只能显式标注

// TODO: 研究以下例子

全新 Javascript 装饰器实战上篇:用 MobX 的方式打开 Vue

全新 JavaScript 装饰器实战下篇:实现依赖注入

TypeScript 5.0 beta 发布:新版 ES 装饰器、泛型参数的常量修饰、枚举增强等

2. 如何启用

以下两种方法都可以开启装饰器语法

  1. @babel/plugin-proposal-decorators · Babel (babeljs.io)

  2. TypeScript: Documentation - Decorators (typescriptlang.org)

3. 概念

装饰器是一种特殊的声明,可以附加到类声明、方法、访问器、属性或参数。

装饰器使用形式 @expression ,其中 expression 必须是计算一个函数,该函数将在运行时调用,其中包含有关修饰声明的信息。

legacy和stage3版本,差别还挺大的

打包结果

js
function __decorate(decorators, target, key, descriptor) {
  const length = arguments.length;
  // 描述符
  let r =
    length < 3
      ? target
      : descriptor === null
        ? descriptor = Object.getOwnPropertyDescriptor(target, key)
        : descriptor;
  let decoratorFunc;
  // 预留Reflect新协议实现
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
    r = Reflect.decorate(decorators, target, key, descriptor);
  }
  else {
    // 反向循环调用函数,先设置类型
    for (let i = decorators.length - 1; i >= 0; i--) {
      decoratorFunc = decorators[i]
      if (decoratorFunc) {
        // 更新描述符,并传递到下一个装饰器
        r = (
          length < 3
          ? decoratorFunc(r) // class
          : length > 3
            ? decoratorFunc(target, key, r) // method
            : decoratorFunc(target, key) // property, param
          ) || r;
      }
    }
  }
  if (length > 3  && r ) {
    Object.defineProperty(target, key, r)
  }

  return r;
}
var __metadata = (this && this.__metadata) || function (key, value) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
        // 返回可运行的装饰器函数
         return Reflect.metadata(key, value);
    }
};
function __param(paramIndex, decorator) {
    return function (target, key) { 
        decorator(target, key, paramIndex); 
    }
};

function ParamDecorator(target, propertyKey, index) {
    console.log('PropertyDecorator', {
        target: target,
        propertyKey: propertyKey,
        index: index,
        type: Reflect.getMetadata('design:type', target, propertyKey).toString(),
    });
}
var ExampleClass = (function () {
    function ExampleClass(a) {
        this.pattern1 = { xx: 1 };
        console.log('init', a);
    }
   ExampleClass.prototype.runPatten = function (input) {
        console.log('log', this.pattern);
        return '111';
    };
    __decorate([
        PropertyDecorator,
        __metadata("design:type", String)
    ], ExampleClass.prototype, "pattern", void 0);
    __decorate([
        PropertyDecorator,
        __metadata("design:type", Object)
    ], ExampleClass.prototype, "pattern1", void 0);
    __decorate([
        PropertyDecorator,
        __metadata("design:type", Array)
    ], ExampleClass.prototype, "pattern2", void 0);
    __decorate([
        PropertyDecorator,
        __param(0, ParamDecorator),
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [String]),
        __metadata("design:returntype", String)
    ], ExampleClass.prototype, "runPatten", null);
      // 返回赋值给类
    ExampleClass = __decorate([
        reportableClassDecorator('hhhh'),
        Con,
        __metadata("design:paramtypes", [String])
    ], ExampleClass);
    return ExampleClass;
}());

类装饰器

函数装饰器

应用的库

Released under the MIT License.