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

TypeScript装饰器:从入门到精通

TypeScript装饰器:从入门到精通

什么是装饰器?

装饰器(Decorator)是TypeScript中一个非常酷的特性,它允许我们在不修改原有代码的情况下,给类、方法、属性等添加额外的功能。想象一下装饰器就像给你的代码"穿衣服",可以一层层地叠加功能,而不会破坏原有的结构。

在ES2016中,装饰器还只是一个提案,但TypeScript已经提前实现了这个功能。要使用装饰器,需要在tsconfig.json中开启experimentalDecorators选项。

装饰器基础

类装饰器

类装饰器是最简单的一种装饰器,它接收一个构造函数作为参数。让我们看个例子:

function logClass(target: Function) {console.log(`${target.name} 被装饰了`);
}@logClass
class MyClass {constructor() {console.log('创建MyClass实例');}
}const myClass = new MyClass();
// 输出:
// 类 MyClass 被装饰了
// 创建MyClass实例

方法装饰器

方法装饰器可以拦截方法的调用,非常适合用于日志记录、权限验证等场景:

function logMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function(...args: any[]) {console.log(`调用方法 ${propertyKey},参数: ${JSON.stringify(args)}`);const result = originalMethod.apply(this, args);console.log(`方法 ${propertyKey} 返回: ${result}`);return result;};return descriptor;
}class Calculator {@logMethodadd(a: number, b: number): number {return a + b;}
}const calc = new Calculator();
calc.add(2, 3);
// 输出:
// 调用方法 add,参数: [2,3]
// 方法 add 返回: 5

装饰器工厂

有时候我们希望装饰器能接收参数,这时候就需要使用装饰器工厂:

function logWithPrefix(prefix: string) {return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function(...args: any[]) {console.log(`[${prefix}] 调用方法 ${propertyKey}`);return originalMethod.apply(this, args);};return descriptor;};
}class Logger {@logWithPrefix('DEBUG')log(message: string) {console.log(message);}
}const logger = new Logger();
logger.log('这是一条日志');
// 输出:
// [DEBUG] 调用方法 log
// 这是一条日志

装饰器的执行顺序

当多个装饰器应用于同一个声明时,它们的执行顺序很重要:

  1. 参数装饰器,然后是方法、访问器或属性装饰器
  2. 装饰器从最靠近声明的装饰器开始执行
  3. 类装饰器最后执行
function first() {console.log('first() 工厂函数');return function(target: any) {console.log('first() 装饰器');};
}function second() {console.log('second() 工厂函数');return function(target: any) {console.log('second() 装饰器');};
}@first()
@second()
class ExampleClass {}// 输出:
// first() 工厂函数
// second() 工厂函数
// second() 装饰器
// first() 装饰器

装饰器的实际应用

1. 自动绑定this

在React类组件中,我们经常需要绑定方法的this指向,装饰器可以帮我们自动完成:

function autobind(_: any, _2: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;const adjDescriptor: PropertyDescriptor = {configurable: true,enumerable: false,get() {const boundFn = originalMethod.bind(this);return boundFn;}};return adjDescriptor;
}class Button {@autobindonClick() {console.log('按钮被点击', this);}
}const button = new Button();
document.addEventListener('click', button.onClick);

2. 表单验证

装饰器可以很方便地实现表单验证逻辑:

function validate(min: number, max: number) {return function(target: any, propertyKey: string) {let value: number;const getter = function() {return value;};const setter = function(newVal: number) {if (newVal < min || newVal > max) {throw new Error(`值必须在 ${min}${max} 之间`);}value = newVal;};Object.defineProperty(target, propertyKey, {get: getter,set: setter});};
}class User {@validate(1, 120)age: number;
}const user = new User();
user.age = 25; // 正常
user.age = 0;  // 抛出错误

装饰器的局限性

虽然装饰器很强大,但也有一些限制:

  1. 不能装饰函数声明(只能装饰类、方法、访问器、属性或参数)
  2. 装饰器不能修改类的结构(比如不能添加或删除类成员)
  3. 目前还是实验性特性,未来可能会有变化

总结

TypeScript装饰器是一个非常强大的元编程工具,它允许我们以声明式的方式为代码添加功能。通过本文的介绍,你应该已经掌握了:

  • 装饰器的基本概念和使用方法
  • 类装饰器、方法装饰器、属性装饰器的区别
  • 如何创建装饰器工厂
  • 装饰器的执行顺序
  • 装饰器在实际项目中的应用场景

装饰器在Angular、NestJS等框架中都有广泛应用,掌握好这个特性,能让你的代码更加优雅和可维护。

相关文章:

  • PyTorch中mean(dim=1)的深度解析
  • k8s 中使用 Service 访问时NetworkPolicy不生效问题排查
  • ubuntu24.04上安装NVIDIA driver+CUDA+cuDNN+Anaconda+Pytorch
  • 计算机视觉最不卷的方向:三维重建学习路线梳理
  • 分布式2(Zookeeper )
  • ubuntu 22.04 wifi网卡配置地址上网
  • OpenHarmony轻量系统--BearPi-Nano开发板网络程序测试
  • 常见排序算法及其java实现
  • Redis缓存穿透、雪崩、击穿的解决方案?
  • 基于OpenCV中的图像拼接方法详解
  • Python----神经网络(《Searching for MobileNetV3》论文概括和MobileNetV3网络)
  • 前端安全:XSS、CSRF 防御与最佳实践
  • 【漫话机器学习系列】259.神经网络参数的初始化(Initialization Of Neural Network Parameters)
  • AI与机器学习深度集成:从设备端能力爆发到开发工具智能化
  • C++笔记-AVL树(包括单旋和双旋等)
  • 比亚迪固态电池突破:王传福的技术哲学与产业重构|创客匠人热点评述
  • 第29节:现代CNN架构-Inception系列模型
  • 深度学习中的查全率与查准率:如何实现有效权衡
  • 在RAG中 如何提高向量搜索的准确性?
  • 视频编解码学习十二之Android疑点
  • 京东回应外卖系统崩溃:订单暴涨所致,已恢复
  • 前四个月人民币贷款增加10.06万亿元,4月末M2余额同比增长8%
  • 颜福庆与顾临的争论:1930年代在中国维持一家医学院要花多少钱
  • 持续8年仍难终了的纠纷:败诉方因拒执罪被立案,胜诉方银行账户遭冻结
  • 外交部亚洲司司长刘劲松会见印度驻华大使罗国栋
  • 民生谣言误导认知,多方联动守护清朗——中国互联网联合辟谣平台2025年4月辟谣榜综述