首页 / 更多教程 / TS简明教程(4)——装饰器
TS简明教程(4)——装饰器
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了TS简明教程(4)——装饰器,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4127字,纯文字阅读大概需要6分钟。
内容图文
![TS简明教程(4)——装饰器](/upload/InfoBanner/zyjiaocheng/1014/d4d263f6ff0f4a3f8de922a4e3038274.jpg)
为了后续内容(如nestjs等框架)的开展,本文更新TS相关的基础知识。
关注获取更多TS精品文章
本文讲解装饰器
装饰器
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,访问符,属性或参数上。装饰器使用@expression这种形式,expression必须是一个函数,它会在运行时被调用,被装饰的声明信息作为参数传入。
Typescript中的装饰器是一项实验性功能,需要在tsconfig.json中开启该特性
{
"compilerOptions": {
"experimentalDecorators": true
}
}
例如,有一个@sealed装饰器,我们这样定义sealed:
function sealed(target: any) {
// 操作被装饰对象
}
装饰器工厂
如果需要给装饰器添加一些动态行为,比如开发一个监控统计的装饰器,需要传入当前统计的事件名称,有多个事件名称时只需要变更传入的事件名而不用重复定义装饰器。
这时候需要使用到装饰器工厂。装饰器工厂也是一个函数,只不过它的返回值是一个装饰器。例如如下的事件监控装饰器:
function event(eventName: string) {
return function(target: any) {
// 获取到当前eventName和被装饰对象进行操作
}
}
装饰器组合
多个装饰器可以同时应用到被装饰对象上,例如下面的例子:
@sealed
@test('test')
class Demo {
}
装饰器执行顺序:
装饰器工厂需要先求值,再装饰,求值顺序是由上到下
装饰器可以直接求值,装饰顺序是由下到上
上面的说明可以难以理解,下面举一个实际的例子:
function f() {
console.log('f求值');
return function(target: any) {
console.log('f装饰');
}
}
function g() {
console.log('g求值');
return function(target: any) {
console.log('g装饰');
}
}
@f()
@g()
class Demo {
}
上例的执行顺序为
f求值
g求值
g装饰
f装饰
因为先求值,所以在上面的f会比g先求值。因为装饰器是由下到上装饰,所以求值后的g比f先执行。
装饰器类型
根据被装饰的对象不同,装饰器分为以下几类:
-
类装饰器
-
方法装饰器
-
属性装饰器
- 函数参数装饰器
类装饰器
类装饰器在定义类的地方。类装饰器可以监视、修改或替换类定义。类的构造函数将作为唯一参数传递给装饰器。如果类装饰器返回一个值,它会使用返回的构造函数替换原来的类声明。
function sealed(target: Function) {
Object.seal(target);
Object.seal(target.prototype);
}
@sealed
class Demo {}
下面来一个替换构造函数的示例:
function replace<T extends {new(...args: any[]):{}}>(target: T) {
return class extends target {
newname = "newName";
age = 18
}
}
@replace
class Demo {
oldname = "oldname";
constructor(oldname: string) {
this.oldname = oldname;
}
}
console.log(new Demo("oldname"));
以上例程会输出
class_1 { oldname: 'oldname', newname: 'newName', age: 18 }
可以看到通过装饰器新增的newname和age属性已经成功注入了。
方法装饰器
方法装饰器用来装饰类的方法(静态方法和实例方法都可以)。方法装饰器可以监视、修改或替换方法定义。
方法装饰器接收3个参数:
-
类的原型对象,如果是静态方法则为类的构造函数
-
方法名称
- 方法的属性描述符
下面是一个修改方法行为的装饰器:
function hack(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const oldFunction = target[propertyKey]; // 获取方法引用
const newFunction = function(...args: any[]) {
console.log('call function ', propertyKey);
oldFunction.call(target, ...args);
}
descriptor.value = newFunction; // 替换原声明
}
class Demo {
@hack
demo() {
console.log('call demo');
}
}
const demo = new Demo();
demo.demo();
以上例程输出如下:
call function demo
call demo
属性装饰器
属性装饰器用来装饰类的成员属性。属性装饰器接收两个参数:
-
类的原型对象,如果是静态方法则为类的构造函数
- 属性名
function demo(value: string) {
return function(target: any, propertyKey: string) {
target[propertyKey] = value;
}
}
class Demo {
@demo('haha') name?: string;
}
const d = new Demo();
console.log(d.name);
属性装饰器多用在属性依赖注入上面
函数参数装饰器
参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
-
对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
-
参数的名字。
- 参数在函数参数列表中的索引。
function PathParam(paramDesc: string) {
return function (target: any, paramName: string, paramIndex: number) {
!target.$meta && (target.$meta = {});
target.$meta[paramIndex] = paramDesc;
}
}
class Demo {
constructor() { }
getUser( @PathParam("userId") userId: string) { }
}
console.log((<any>Demo).prototype.$meta);
以上例程输出
{ '0': 'userId' }
函数参数装饰器可以用在开发Web框架时自动注入请求参数。结语
装饰器的介绍到这里就暂时结束了,装饰器的存在让Typescript有了与Java和C#等语言的注解相同的功能。当然,基于装饰器能做的工作是相当多的,注明的Angular2就大量使用了装饰器来分离业务逻辑。
对装饰器有想法的小伙伴可以扫码加我进行交流
内容总结
以上是互联网集市为您收集整理的TS简明教程(4)——装饰器全部内容,希望文章能够帮你解决TS简明教程(4)——装饰器所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。