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

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等框架中都有广泛应用,掌握好这个特性,能让你的代码更加优雅和可维护。

http://www.xdnf.cn/news/6320.html

相关文章:

  • LangChain4j入门(一)SpringBoot整合并接入Deepseek
  • 前端~三维地图(cesium)动态材质飞线
  • nacos:服务无法注册到nacos服务中心
  • Linux 动静态库详解
  • JS 中 Object.keys() 和 Object.values() 的深度解析与应用
  • 蓝桥杯 17. 修改数组
  • 【Linux高级IO】多路转接之epoll
  • Linux——mysql主从复制与读写分离
  • 人工智能+ERP:政策新规下企业智能化转型路径
  • 【vue】axios网络请求介绍
  • 【2025版】Spring Boot面试题
  • C语言_自定义类型:结构体
  • (4)python开发经验
  • (十七)Java日期时间API全面解析:从传统Date到现代时间处理
  • Ros2 - Moveit2 - DeepGrasp(深度抓握)
  • golang -- 如何让main goroutine等一等
  • 数智驱动——AI:企业数字化转型的“超级引擎”
  • FreeRTOS学习笔记
  • 【Java学习笔记】finalize方法
  • 前后端分离博客 Weblog 项目实战
  • 【AI大模型】赋能【传统业务】
  • Java基础语法之数组
  • Windows下Docker安装portainer
  • 64. 最小路径和
  • Shell 脚本中的通道号(文件描述符)
  • maven项目, idea右上角一直显示gradle的同步标识, 如何去掉
  • 计算机网络:什么是计算机网络?它的定义和组成是什么?
  • 开源Heygem本地跑AI数字人视频教程
  • python使用matplotlib画图
  • IDEA编辑器设置的导出导入