【TypeScript入坑】TypeScript 的装饰器
装饰器
简介
装饰器(Decorator
)是一种语法结构,用来在定义时修改类(class
)的行为。
在语法上,装饰器有如下几个特征。
- 第一个字符(或者说前缀)是
@
,后面是一个表达式。 @
后面的表达式,必须是一个函数(或者执行后可以得到一个函数)。- 这个函数接受所修饰对象的一些相关值作为参数。
- 这个函数要么不返回值,要么返回一个新对象取代所修饰的目标对象。
🤏 举个栗子,有一个函数 simpleDecorator()
当作装饰器使用,那么需要写成@simpleDecorator
,然后放在某个类的前面。
function simpleDecorator(target: any, context: any) {
console.log("hi, this is " + target);
return target;
}
@simpleDecorator
class A {} // "hi, this is class A {}"
装饰器的结构
👇 装饰器函数的类型定义如下。
type Decorator = (
value: DecoratedValue,
context: {
kind: string;
name: string | symbol;
addInitializer?(initializer: () => void): void;
static?: boolean;
private?: boolean;
access: {
get?(): unknown;
set?(value: unknown): void;
};
}
) => void | ReplacementValue;
👇 解释:
value
:所装饰的对象context
:上下文对象kind
:字符串,表示所装饰对象的类型name
:字符串或Symbol值,所装饰对象的名字addInitializer()
:函数,用来添加类的初始化逻辑private
:布尔值,判断所装饰的对象是否为类的私有成员static
:布尔值,所装饰对象是否为类的静态成员。access
:一个对象,包含了某个值的get
和set
方法。
类装饰器
👇 类装饰器的类型描述如下。
type ClassDecorator = (
value: Function, // 当前类本身
context: {
kind: "class";
name: string | undefined;
addInitializer(initializer: () => void): void;
} // 上下文对象
) => Function | void;
类装饰器一般用来对类进行操作,可以不用返回任何值。
function Greeter(value, context) {
if (context.kind === "class") {
value.prototype.greet = function () {
console.log("你好");
};
}
}
@Greeter
class User {}
let u = new User();
u.greet(); // "你好"
类装饰器可以返回一个函数,替代当前类的构造方法。也可以返回一个新的类,替代原来所装饰的类。
方法装饰器
👇 方法装饰器用来装饰类的方法(method
)。它的类型描述如下。
type ClassMethodDecorator = (
value: Function,
context: {
kind: "method";
name: string | symbol;
static: boolean;
private: boolean;
access: { get: () => unknown };
addInitializer(initializer: () => void): void;
}
) => Function | void;
如果方法装饰器返回一个新的函数,就会替代所装饰的原始函数。
function replaceMethod() {
return function () {
return `How are you, ${this.name}?`;
};
}
class Person {
constructor(name) {
this.name = name;
}
@replaceMethod
hello() {
return `Hi ${this.name}!`;
}
}
const robin = new Person("Robin");
robin.hello(); // 'How are you, Robin?'
属性装饰器
属性装饰器用来装饰定义在类顶部的属性(field
)。它的类型描述如下。
type ClassFieldDecorator = (
value: undefined,
context: {
kind: "field";
name: string | symbol;
static: boolean;
private: boolean;
access: { get: () => unknown; set: (value: unknown) => void };
addInitializer(initializer: () => void): void;
}
) => (initialValue: unknown) => unknown | void;
属性装饰器要么不返回值,要么返回一个函数,该函数会自动执行,用来对所装饰属性进行初始化。该函数的参数是所装饰属性的初始值,该函数的返回值是该属性的最终值。
function logged(value, context) {
const { kind, name } = context;
if (kind === "field") {
return function (initialValue) {
console.log(`initializing ${name} with value ${initialValue}`);
return initialValue;
};
}
}
class Color {
@logged name = "green";
}
const color = new Color();
// "initializing name with value green"
getter装饰器,setter装饰器
getter
装饰器和 setter
装饰器,是分别针对类的取值器(getter
)和存值器(setter
)的装饰器。它们的类型描述如下。
这两个装饰器要么不返回值,要么返回一个函数,取代原来的取值器或存值器。
accessor装饰器
装饰器语法引入了一个新的属性修饰符 accessor
。
class C {
accessor x = 1;
}
上面代码中,accessor
修饰符等同于为属性x
自动生成取值器和存值器,它们作用于私有属性x。也就是说,上面的代码等同于下面的代码。
class C {
#x = 1;
get x() {
return this.#x;
}
set x(val) {
this.#x = val;
}
}
装饰器的执行顺序
装饰器的执行分为两个阶段。
- 评估(evaluation):计算
@
符号后面的表达式的值,得到的应该是函数。 - 应用(application):将评估装饰器后得到的函数,应用于所装饰对象。
也就是说,装饰器的执行顺序是,先评估所有装饰器表达式的值,再将其应用于当前类。
应用装饰器时,顺序依次为方法装饰器和属性装饰器,然后是类装饰器。
原文地址:https://blog.csdn.net/XH_jing/article/details/142384716
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!