当前位置: 首页 > news >正文

【NestJS入门到精通】装饰器

目录

  • 方法装饰器
    • 通过prototype添加属性、方法
  • 属性装饰器
    • 拓展
  • 方法装饰器
  • 参数装饰器

在这里插入图片描述

方法装饰器

ClassDecorator

定义了一个类装饰器 a,并将其应用于类 A。装饰器 a 会在类 A 被定义时执行。

const a:ClassDecorator = (target:any)=>{console.log(target,target)//[class A] [class A]
}@a
class A {constructor(){}
}

上面代码等价于下面代码

const a:ClassDecorator = (target:any)=>{console.log(target,target)//[class A] [class A]
}class A {constructor(){}
}
a(A)

通过prototype添加属性、方法

定义一个 ClassDecorator,这个装饰器的作用是修改类A 的原型,@a 装饰器为类 A 添加了一个 name 属性。具体来说,装饰器 aname 属性添加到了 A 类的 prototype 上,因此所有通过 A 类创建的实例都能够访问这个 name 属性。

const a:ClassDecorator = (target:any)=>{target.prototype.name = "张三"
}@a
class A {constructor(){}
}const test:any = new A();
console.log(test)//A {}. 输出实例 A,内容包括 constructor 和原型链上的属性 `name`
console.log(test.name)//张三
  • 动态添加属性:使用装饰器,你可以动态为类或其实例添加属性、方法或者进行其他操作,而不需要直接修改类的定义。这使得代码更加灵活,可以根据上下文条件来修改类的行为。

  • 减少重复代码:如果你需要在多个类上应用相似的逻辑,比如为多个类都添加 name 属性,使用装饰器可以避免在每个类中都手动添加相同的代码。

  • 提高可读性:通过装饰器,相关的逻辑集中在一个地方,便于理解和维护。你可以将通用功能提取到装饰器中,而不是散落在多个类中。

属性装饰器

PropertyDecorator

  • target 是空对象 {},实际上是 A.prototype,这是因为 name 是实例属性,而实例属性存储在类的原型链中。
  • key 是 name,表示被装饰的属性名称。
const a: PropertyDecorator = (target: any, key: string | symbol) => {console.log(target, key)//{} name
}class A {@apublic name: string;constructor() {this.name = "张三";}
}
  • 灵活的元数据处理:你可以在属性被定义时拦截并处理它,添加额外的行为或逻辑。例如,记录属性的变化、定义特定的验证规则等。

  • 解耦的功能增强:通过装饰器,你可以将逻辑与类的主要业务逻辑解耦开来。比如,可以为某个属性自动添加 getter/setter 方法,或者在装饰器中为属性附加元数据。

  • 代码简洁性:装饰器可以让代码更加简洁和可读,减少在类中重复编写相同的逻辑。

拓展


const a: PropertyDecorator = (target: any, key: string | symbol) => {let value: string;Object.defineProperty(target, key, {get() {console.log( `修改后的值: ${value}`)// 修改返回的值return value},set(newvalue) {console.log(`${String(key)} 被赋值为 ${newvalue}`);value = newvalue;},});
};class A {@apublic name: string;constructor() {this.name = "张三"; // 当调用时,setter 会生效}
}const test = new A();
test.name = "里斯"
console.log(test.name); 

打印的先后顺序

name 被赋值为 张三
name 被赋值为 里斯
修改后的值: 里斯
里斯

装饰器在类定义的时候就会被执行

方法装饰器

  • target 是 A.prototype,即类 A 的原型对象,因为装饰器应用在类的实例方法 getName 上。
  • key 是被装饰方法的名称,在这里是 “getName”
  • descriptor 是方法的 属性描述符,包含关于方法的一些信息,例如可写性、可枚举性等。
const a: MethodDecorator = (target: any, key: string | symbol,descriptor:any) => {console.log(target,key,'descriptor')
};
class A {public name: string;constructor() {this.name = "张三"; }@agetName(){}
}
// console.log(target,key,'descriptor') 打印结果
{} getName {value: [Function: getName],writable: true,enumerable: false,configurable: true
}

参数装饰器

需要用到ParameterDecorator装饰器,且装饰器的第三个参数parameterIndex为参数的索引,即第几个参数。

  • target:是方法所在类的原型对象。在这个例子中,target 为 {},这是 A.prototype,表示 A 类的原型。
  • propertyKey:是方法的名称。在这个例子中是 “getName”,因为装饰器被应用在 getName 方法的参数上。
  • parameterIndex:是参数的索引。在这个例子中是 1,表示装饰器应用在 getName 方法的第二个参数(age)上。

const a: ParameterDecorator = (target: Object, propertyKey: string | symbol | undefined, parameterIndex: number) => {console.log(target, propertyKey, parameterIndex); //{} getName 1
};class A {public name: string;constructor() {this.name = "张三";}getName(name: string, @a age: number) {// age 参数被装饰器修饰}
}

在写参数装饰器可能会报错,比如:

在这里插入图片描述
原因是因为设定的参数类型,与定义的ParameterDecorator类型不一致。
ParameterDecorator类型如下:
其中 propertyKey: string | symbol | undefined

declare type ParameterDecorator = (target: Object, propertyKey: string | symbol | undefined, parameterIndex: number) => void;

所以我们需要修改方法a的定义,上文已经是正确的定义方法。

const a: ParameterDecorator = (target: Object, propertyKey: string | symbol | undefined, parameterIndex: number) => {console.log(target, propertyKey, parameterIndex); 
};
http://www.lryc.cn/news/460132.html

相关文章:

  • XML 编辑最简单好用的 QXmlEdit 软件已经完整中文化
  • ref标签、style的scope
  • 22年408数据结构
  • ubuntu 虚拟机将linux文件夹映射为windows网络位置
  • Pytho逻辑回归算法:面向对象的实现与案例详解
  • AWS WAF实战指南:从入门到精通
  • k8s的部署
  • C# 两个进程/exe通讯方式 两个应用程序通讯方式
  • ubuntu下打开摄像头
  • ABAP 表转JSON格式
  • oceanbase的日志量太大,撑爆磁盘,修改下日志级别
  • 【C++11】lambda表达式
  • 前端学习-css的背景(十六)
  • 使用Postman搞定各种接口token实战
  • ssh连接慢的问题或远程连接服务超时
  • 基于卷积神经网络的蔬菜识别系统,resnet50,mobilenet模型【pytorch框架+python源码】
  • 数据结构与算法:栈与队列的高级应用
  • macos php开发环境之macport安装的php扩展安装,php常用扩展安装,port中可用的所有php扩展列表
  • 使用Pytorch+Numpy+Matplotlib实现手写字体分类和图像显示
  • kimi帮我解决ubuntu下软链接文件夹权限不够的问题
  • 如何去除背景音乐保留人声?保留人声,消除杂音
  • 2.4.ReactOS系统提升IRQL级别KfRaiseIrql 函数
  • 【新书】使用 OpenAI API 构建 AI 应用:利用 ChatGPT等构建 10 个 AI 项目(第二版),404页pdf
  • 修改PostgreSQL表中的字段排列顺序
  • canvas实现手写功能
  • Python知识点:基于Python技术,如何使用TensorFlow进行目标检测
  • 初始爬虫13(js逆向)
  • 前端发送了请求头的参数,经debug发现后端请求对象请求头中没有该参数
  • 雷池社区版如何使用静态资源的方式建立站点
  • 车载电源OBC+DC/DC