TypeScript(八)装饰器

本文详细介绍了TypeScript中的装饰器,包括类装饰器、方法装饰器、属性装饰器、存取器装饰器和参数装饰器的使用,以及装饰器的优先级和工厂模式。通过示例展示了如何修改类行为、参数过滤以及装饰器与ReactHooks的兼容性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前言

定义

类装饰器

基本用法

操作方式

操作类的原型

类继承操作

方法装饰器

属性装饰器

存取器装饰器

参数装饰器

基本用法

参数过滤器

元数据函数实现

参数过滤

效果实践

装饰器优先级

相同装饰器

不同装饰器

装饰器工厂

hooks与class兼容

结语

相关文章


前言

本文收录于TypeScript知识总结系列文章,欢迎指正! 

程序遵循开放封闭原则,即在设计和编写软件时应该尽量避免对原有代码进行修改,而是通过添加新的代码来扩展软件的功能。

在日常开发中不知你有没有遇到以下情况,我们封装了一个Request模块,现在需要对请求进行拦截,访问请求参数,此时我们可以通过装饰器针对请求函数或者请求类进行访问,获取参数并解析

定义

在TS中,装饰器是一种特殊类型的声明。可以附加到类、方法、属性或参数上用于修改类的行为或属性。

在面向对象编程中,有时需要对类的行为和功能做出修改,直接修改类的内部可能会使成本升高,或出现其他问题;此时可以使用装饰器来修改类,在保证类内部结构与功能不变的前提下对数据或行为进行迭代

TS中装饰器可以分为类装饰器、方法装饰器、属性装饰器和参数装饰器。

tips:使用装饰器前需要在tsconfig中开启experimentalDecorators属性

类装饰器

类装饰器是应用于类的构造函数的函数,它可以用来修改类的行为。类装饰器可以有一个参数,即类的构造函数,通过这个参数我们可以对类的行为进行修改。

基本用法

类装饰器的语法是在一个普通的函数名前面加上@符号,后面紧跟着要装饰的类的声明,如:

const nameDecorator = (constructor: typeof Animal) => {
    console.log(constructor.prototype.name)// undefined
}
@nameDecorator
class Animal {
    name: string = "阿黄"
    constructor() {
        console.log(this.name);// 阿黄
    }
}
new Animal()

在上述代码中,我使用decorator获取Animal类的name属性,发现获取的是未定义,而在构造函数中却可以获取,原因是类的装饰器是在类定义时对类进行操作的,而属性及函数的初始化是当类实例化时进行的,所以获取不到name的值

操作方式

通过类装饰器操作类的方式有两种:操作类的原型和类的继承

操作类的原型

ES6之前的类是通过构造函数实现的,其原型prototype属性是存在的,所以我们在对类进行操作时可以使用修改原型的方式

type IAnimal = {
    name?: string
    getName?: () => string
}
const nameDecorator = (constructor: Function) => {
    const _this = constructor.prototype // 模拟类内部环境
    _this.name = "阿黄"
    _this.getName = () => {
        return _this.name
    }
}
@nameDecorator
class Animal implements IAnimal { }
const animal: IAnimal = new Animal()
console.log(animal.getName()) // 阿黄

上面代码实现了对类中name属性初始化以及实现了类的getName方法,在ES5中如何实现类的重写?看看下面代码对装饰器的修改:

const nameDecorator = (constructor: IAnimalProto) => {
    const _this = constructor.prototype // 模拟类内部环境
    _this.name = "阿黄"
    return class extends constructor {
        getName = () => {
            return "名字:" + _this.name
        }
    }
}

tips:如果通过这种方式无法修改类的属性或方法,可以把tsconfig中target属性调整为ES5,兼容低版本浏览器,此时类是通过构造函数实现的

类继承操作

ES6中的类语法糖中没有prototype属性,所以我们可以使用继承的方式实现上面的代码,并使用重写的方式修改类中的同名函数

type IAnimal = {
    name?: string
    getName?: () => string
}
type IAnimalProto = {
    new(): Animal
} & IAnimal
const nameDecorator = (constructor: IAnimalProto) => {
    return class extends constructor {
        constructor(public name = "阿黄") {
            super()
        }
        getName() {// 重写类中的函数
            return "姓名:" + this.name
        }
    }
}
@nameDecorator
class Animal implements IAnimal {
    name?: string;
    getName() {
        return this.name
    }
}
const animal: IAnimal = new Animal()
console.log(animal.getName()) // 姓名:阿黄
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿宇的编程之旅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值