修饰器
Youky ... 2023-6-20 About 2 min
# 修饰器
装饰器是 TS 中的一种语法,以 @
开头,只能用于类和类成员(类、属性、方法、方法参数)。
其本质上是一个函数,只不过入参是提前确定的。通常使用工厂函数创建修饰器,这样使用时修饰器可以接受不同的参数。
# 类装饰器
类修饰器直接作用于类上,其接受唯一参数 target 是类本身。
通过类修饰器,可以读取类的信息,新增或覆盖类的属性与方法。通过修改 target 可以修改其静态属性,修改 target.prototype
可以修改其原型链上(可被实例化和继承)的属性。
function Add(num: number) {
return function (target: any) {
target.age = target.age + num
target.prototype.num = num * 10
}
}
@Add(1)
class People {
static age = 1
}
const a = new People() as any
console.log(People.age) // 2
console.log(a.num) // 10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
如果在类修饰器中返回一个新的类,可以覆盖整个类的实现。:
function ReWrite(Target: any) {
return class Sub extends Target {
// 重写log方法
static log(str: string) {
console.log("new log")
}
// 子类新增的方法
static print() {
console.log("print")
}
}
}
@ReWrite
class Logger {
static log(str: string) {
console.log(str)
}
}
Logger.log("abc")(
// new log
Logger as any
).print() // print
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 属性装饰器
# 方法装饰器
方法装饰器的入参包括类的原型(不是类本身)、方法名以及方法的属性描述符(PropertyDescriptor),通过属性描述符可以控制这个方法的内部实现(value)、**可变性(writable)**等信息。
能拿到原本实现,也意味着,我们可以在执行原本方法的同时插入一段新的逻辑。比如计算函数执行耗时:
function TimeLog(target, name, descriptor: any) {
const original = descriptor.value
descriptor.value = async () => {
const pre = Date.now()
await original()
const cost = Date.now() - pre
console.log("Cost: ", cost)
}
}
class Foo {
@TimeLog
static async fetch() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(""), 3000)
})
}
}
Foo.fetch() // Cost: 3016
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18