javascript装饰器进入stage3了

2022-05-06 10:47:29 浏览数 (1)

前言

在3月底,js的装饰器提案终于进入了stage3,同时其metadata部分单独拆开仍处于stage2阶段([详见](https://github.com/tc39/proposal-decorators/pull/454))。但是此装饰器却非平时我们广泛使用的装饰器。通过本文我们将了解下该js提案下装饰器的用法并对比和先前装饰器提案下用法的区别

decorator提案的历史

在[babel-plugin-proposal-decorators](https://babeljs.io/docs/en/babel-plugin-proposal-decorators#docsNav)的文档我们可以看到,decorator提案之前主要经历了3个阶段 目前进入stage3阶段移除metadata的版本共4个版本。下文分别简称(legacy、2018-09、2021-12、stage3)

  • legacy stage 1阶段的提案,也是目前广为使用的用法,也基本等同于Typescript中开启experimentalDecorators的用法
  • 2018-09 在2018.9进入stage2阶段后的提案,此时用法已经完全和stage1不一样
  • 2021-12 2021.12针对此前的stage2提案又做了一次修改,用法又做了一点小修改
  • stage3 最近正式进入stage3的提案。对比2021-12只是去掉了metadata部分,提案本身没有太大的改变。不出意外这也是以后作为标准的装饰器
详细用法
legacy

我们广为使用的用法。即Typescript中tsconfig中配置experimentalDecorators:true

代码语言:javascript复制
{
	"compileOptions": {
		"experimentalDecorators": true
	}
}

或者@babel/plugin-proposal-decorators配置

legacy: true。注意:最新的@babel/plugin-proposal-decorators已经将该配置迁移到version字段,即version: legacy

legacy下的装饰器更具体用法可以参考此前写的一篇文章2020的最后一天,不妨了解下装饰器。

装饰器函数的签名主要如下

代码语言:javascript复制
  type decorator = (
    target: Target | Target.prototype,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) => Function | void;
stage3

本次进入stage3提案的用法

装饰器函数签名如下:

代码语言:javascript复制
type Decorator = (value: Input, context: {
  kind: string;
  name: string | symbol;
  access: {
    get?(): unknown;
    set?(value: unknown): void;
  };
  isPrivate?: boolean;
  isStatic?: boolean;
  addInitializer?(initializer: () => void): void;
}) => Output | void;

装饰器函数包含两个入参参数

1、被装饰的值本身

2、被装饰值的上下文信息

  • kind :"class"|"method"|"getter"|"setter"|"field"|"accessor"。表示装饰器的类型
  • name 装饰值的名称
  • access 同个该属性读写值
  • isStatic 是否静态属性
  • isPrivate 是否私有属性
  • addInitializer 用于执行一些初始化逻辑

各种不同类型的装饰器如下

此外stage3对比legacy提案特有的两个用法

2018-09&2021-12

由于这两种用法在实际中很少特别使用这里只作简单差异化介绍

总结

stage3对比legacy

  1. 除了上面提到的语法区别。legacy装饰器是用“Target”(由当前被装饰目标决定是类本身还是类的原型)调用的,而在stage3中,不再提供这个Target给装饰器函数
  2. legacy装饰器会提供一个完整的descriptor对象,而stage3中只提供被装饰的值以及和它有关的上下文对象。在stage3中修改一个属性的attribute是不可能的,并且 getter 和 setter 不是“合并”而是单独被装饰

stage3对比2018-09

  1. 上面提到的语法的区别
  2. 功能上stage3是2018-09的子集
参考

tc39/proposal-decorators

0 人点赞