今天咱们聊聊装饰器,这玩意儿在TypeScript和现代前端框架里出场率越来越高,但总让人觉得有点“魔法”色彩。别把它想得太玄乎,其实它就是一种特殊的语法,让你能优雅地给类、方法或者属性“加点料”。
![图片[1]-什么是装饰器?如何使用?-速码派](http://www.sumapai.com/wp-content/uploads/2026/01/e84cf742de2841db88e1d7f6840b22fctplv-tb4s082cfz-aigc_resize_2400_2400-1-1024x683.webp)
你可以把装饰器想象成一个高级的包装纸。你想送个礼物(比如一个类或者一个函数),但觉得光秃秃的不够好看,就用包装纸(装饰器)给它包一层,加点丝带啊、卡片啊(也就是额外的功能)。最关键的是,你不用拆开礼物本身去修改它。
看看它长什么样。一个最简单的装饰器就是一个函数,它会在运行时被调用,接收到的参数就是它要装饰的那个目标。比如给类用的装饰器:
function LogClass(constructor: Function) {
console.log(`装饰的类是: ${constructor.name}`);
}
@LogClass
class MyService {
// ...
}
当你运行这段代码,控制台就会立刻打出装饰的类是: MyService。这个@LogClass就是装饰器语法,它直接作用在MyService这个类上。LogClass函数在类被定义的时候就执行了,constructor参数就是类的构造函数。
方法装饰器更常用,也更有意思。它能让你在方法执行前后“插一脚”。
function LogMethod(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`调用方法: ${key}, 参数:`, args);
const result = originalMethod.apply(this, args);
console.log(`方法 ${key} 执行完毕`);
return result;
};
return descriptor;
}
class Calculator {
@LogMethod
add(x: number, y: number) {
return x + y;
}
}
这时候你调用calculator.add(1, 2),控制台会先打印出调用信息和参数,执行完原方法后再打印一条完成信息。看到了吗?我们不动add方法内部一行代码,就给它加上了完整的日志功能。这就是装饰器的威力——面向切面编程。像日志、性能监控、权限校验这种横跨多个方法的通用逻辑,用装饰器来封装是再合适不过了。
除了类和方法,属性、访问器(getter/setter)甚至参数也都能被装饰。不过得提醒你,要玩转装饰器,你得先在tsconfig.json里把experimentalDecorators这个选项设为true,因为这在ECMAScript里还是个提案,不算最终标准。
用的时候也悠着点。装饰器堆叠太多,代码的执行顺序会变得难以跟踪,调试起来有点头疼。我的建议是,把装饰器用在那些真正通用的、非业务核心的横切关注点上。如果你发现某个装饰器里的逻辑跟某个具体业务绑得特别死,那可能就该考虑换种实现方式了。



























暂无评论内容