JS装饰器(Decorator)完全指南 🎨
什么是装饰器?
装饰器(Decorator)是一种特殊类型的声明,它能够被附加到类声明、方法、属性或参数上,可以用来修改类的行为。通俗来说,装饰器就是一个函数,用来修改类的行为。
🔔 注意:目前装饰器已进入 Stage 3 提案阶段,即将成为 ECMAScript 的标准特性。
前置准备工作 ⚙️
1. 开发环境配置
- VSCode 设置中启用装饰器语法支持
- 确保 TypeScript 配置中
experimentalDecorators选项为true
2. 必要依赖安装 📦
bash
npm install --save-dev @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties3. Babel 配置 🛠️
json
{
"babel": {
"presets": ["react-app"],
"plugins": [
["@babel/plugin-proposal-decorators", { "version": "2023-05" }],
["@babel/plugin-proposal-class-properties"]
]
}
}装饰器的使用方式 💡
1. 类装饰器
类装饰器用于整个类的声明之前,可以监视、修改或替换类的定义。
javascript
// 基础类装饰器
const logger = (target) => {
// target 是类本身
target.logger = true;
target.prototype.log = function(...args) {
console.log(...args);
}
};
@logger
class Example {
constructor() {
console.log('Creating new instance');
}
}
// 装饰器工厂(带参数的装饰器)
const withPrefix = (prefix) => {
return (target) => {
target.prototype.getNameWithPrefix = function() {
return `${prefix}_${this.name}`;
}
}
};
@withPrefix('app')
class User {
name = 'john';
}2. 方法装饰器 🔧
方法装饰器可以用来监视、修改或者替换方法定义。
javascript
// 性能监控装饰器
const measurePerformance = (target, propertyKey, descriptor) => {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
const start = performance.now();
const result = originalMethod.apply(this, args);
const end = performance.now();
console.log(`${propertyKey} 执行时间: ${end - start}ms`);
return result;
};
return descriptor;
};
class API {
@measurePerformance
async fetchData() {
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 1000));
return { data: 'success' };
}
}3. 属性装饰器 📝
javascript
// 只读属性装饰器
const readonly = (target, propertyKey) => {
Object.defineProperty(target, propertyKey, {
writable: false
});
};
class Config {
@readonly
static VERSION = '1.0.0';
}实践建议 ✨
性能考虑:装饰器会在类定义时执行,而不是实例化时,要注意性能开销。
调试技巧:使用装饰器时,建议添加适当的日志,便于调试。
最佳实践:
- 保持装饰器功能单一
- 避免在装饰器中进行过重的计算
- 合理使用装饰器工厂来传递参数
常见应用场景 🎯
- 权限控制
javascript
const requireAuth = (target, propertyKey, descriptor) => {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
if (!this.isAuthenticated) {
throw new Error('未授权访问');
}
return originalMethod.apply(this, args);
};
};- 数据验证
javascript
const validateParams = (schema) => {
return (target, propertyKey, descriptor) => {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
const valid = schema.validate(args[0]);
if (!valid) {
throw new Error('参数验证失败');
}
return originalMethod.apply(this, args);
};
};
};注意事项 ⚠️
- 装饰器执行顺序:从下到上,从右到左
- 不同类型装饰器的参数可能不同
- 某些装饰器可能会影响类的原型链
- 需要注意浏览器兼容性问题
💡 提示:建议在正式使用装饰器之前,先在测试环境中充分验证其行为。