装饰器
[说明] Decorator 提案经历了重大的语法变化,目前处于第三阶段,定案之前不知道是否还有变化。本章现在属于草稿阶段,凡是标注“新语法”的章节,都是基于当前的语法,不过没有详细整理,只是一些原始材料;未标注“新语法”的章节基于以前的语法,是过去遗留的稿子。之所以保留以前的内容,有两个原因,一是 TypeScript 装饰器会用到这些语法,二是里面包含不少有价值的内容。等到标准完全定案,本章将彻底重写:删去过时内容,补充材料,增加解释。(2022年6月)
简介(新语法)
装饰器(Decorator)用来增强 JavaScript 类(class)的功能,许多面向对象的语言都有这种语法,目前有一个提案将其引入了 ECMAScript。
装饰器是一种函数,写成@ + 函数名
,可以用来装饰四种类型的值。
- 类
- 类的属性
- 类的方法
- 属性存取器(accessor)
下面的例子是装饰器放在类名和类方法名之前,大家可以感受一下写法。
javascript
@frozen class Foo {
@configurable(false)
@enumerable(true)
method() {}
@throttle(500)
expensiveMethod() {}
}
上面代码一共使用了四个装饰器,一个用在类本身(@frozen),另外三个用在类方法(@configurable()、@enumerable()、@throttle())。它们不仅增加了代码的可读性,清晰地表达了意图,而且提供一种方便的手段,增加或修改类的功能。
装饰器 API(新语法)
装饰器是一个函数,API 的类型描述如下(TypeScript 写法)。
typescript
type Decorator = (value: Input, context: {
kind: string;
name: string | symbol;
access: {
get?(): unknown;
set?(value: unknown): void;
};
private?: boolean;
static?: boolean;
addInitializer?(initializer: () => void): void;
}) => Output | void;
装饰器函数有两个参数。运行时,JavaScript 引擎会提供这两个参数。
value
:所要装饰的值,某些情况下可能是undefined
(装饰属性时)。context
:上下文信息对象。
装饰器函数的返回值,是一个新版本的装饰对象,但也可以不返回任何值(void)。
context
对象有很多属性,其中kind
属性表示属于哪一种装饰,其他属性的含义如下。
kind
:字符串,表示装饰类型,可能的取值有class
、method
、getter
、setter
、field
、accessor
。name
:被装饰的值的名称: The name of the value, or in the case of private elements the description of it (e.g. the readable name).access
:对象,包含访问这个值的方法,即存值器和取值器。static
: 布尔值,该值是否为静态元素。private
:布尔值,该值是否为私有元素。addInitializer
:函数,允许用户增加初始化逻辑。
装饰器的执行步骤如下。
- 计算各个装饰器的值,按照从左到右,从上到下的顺序。
- 调用方法装饰器。
- 调用类装饰器。
未完待续。。。