装饰器
介绍
装饰器其实就是一个函数,通过注入的方式到类、方法、属性、参数上,拓展其功能。
注意 装饰器是一项实验性特性,在未来的版本中可能会发生改变。
所以,需要在tsconfig.json
中开启兼容
1
| "experimentalDecorators": true,
|
装饰器使用语法如下:
1 2 3 4 5
| function fun1() { }
@fun1 class Person1 {}
|
类装饰器
1 2 3 4 5 6 7 8 9 10 11 12
| function fun1(target: any) { target.prototype.name = "lisi"; }
@fun1 class Person1 {}
let p1 = new Person1();
console.log(p1.name);
|
这里的类装饰器不能传递参数,如果需要传参@fun1(arg),则需要使用装饰器工厂
装饰器工厂
其实就是返回一个函数,外面的函数用来接收参数,里面的函数用来就是一个装饰器。(函数柯里化)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function fun2(value: any) { return function (target: any) { target.prototype.username = value.username; target.prototype.age = value.age; }; } @fun2({ username: "zhangsan", age: 18, }) class Person2 {} let p2 = new Person2();
console.log(p2.username, p2.age);
|
如果说同时使用了装饰器工厂和装饰器,那么它们的执行顺序不是从上到下的规律
装饰器组合
可以对同一个类使用多个装饰器和装饰器工厂。执行顺序如下:
- 执行所有的装饰器工厂,获取到装饰器
- 从下到上执行装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function demo1(target: any) { console.log("demo1"); } function demo2() { console.log("demo2"); return (target: any) => { console.log("demo2 into"); }; } function demo3() { console.log("demo3"); return (target: any) => { console.log("demo3 into"); }; } function demo4(target: any) { console.log("demo4"); }
@demo1 @demo2() @demo3() @demo4 class Person3 {}
|
因此,打印结果如下:
1 2 3 4 5 6
| demo2 demo3 demo4 demo3 into demo2 into demo1
|
属性装饰器
装饰属性
参数:
- 对于静态属性来说是类的构造函数,对于实例属性是类的原型对象
- 属性的名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
function fun3(value: any) { return function (target: any, propertyKey: any) { target[propertyKey] = value; }; } class Person4 { @fun3("wangwu") name: string; } let p4 = new Person4(); console.log(p4.name);
|
方法装饰器
方法装饰器声明在一个方法的声明之前(紧靠着方法声明)。 它会被应用到方法的 属性描述符上,可以用来监视,修改或者替换方法定义。
方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
- 对于静态方法来说是类的构造函数,实例方法则是类的原型对象
- 方法名
- 方法的属性描述符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function fun4() { return function (target: any, propertyKey: any, descriptor: any) { console.log(target, propertyKey, descriptor); }; }
class Person5 { @fun4() satName() { console.log("say name"); } }
|
打印结果:
1 2 3 4 5 6
| {} satName { value: [Function: satName], writable: true, enumerable: false, configurable: true }
|
参数装饰器
参数装饰器用来装饰参数
参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
- 成员的名字
- 参数在函数参数列表中的索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function fun5(target: any, propertyKey: string, parameterIndex: number) { console.log(target); console.log("key " + propertyKey); console.log("index " + parameterIndex); }; class Person6 { name: string; constructor() { this.name = 'junjie'; } getName(@fun5 name: string){ return name } } const user = new Person6(); user.name = 'user' console.log(user.name)
|
输出结果:
1 2 3 4
| {} key getName index 0 user
|