js 实现装饰器
装饰器的基本概念
装饰器是一种特殊类型的声明,能够附加到类、方法、属性或参数上,以修改或扩展其行为。在 JavaScript 中,装饰器目前处于提案阶段(Stage 3),需通过 Babel 或 TypeScript 等工具支持。
启用装饰器语法
在项目中使用装饰器前,需配置编译环境:
- TypeScript:在
tsconfig.json中启用experimentalDecorators:{ "compilerOptions": { "experimentalDecorators": true } } - Babel:安装
@babel/plugin-proposal-decorators插件并配置:{ "plugins": [ ["@babel/plugin-proposal-decorators", { "legacy": true }] ] }
类装饰器
类装饰器应用于类构造函数,用于修改或替换类定义。
function logClass(target: Function) {
console.log(`Class ${target.name} is decorated.`);
}
@logClass
class MyClass {}
// 输出:Class MyClass is decorated.
方法装饰器
方法装饰器用于拦截方法调用,接收三个参数:目标对象、方法名和方法描述符。
function readonly(target: any, key: string, descriptor: PropertyDescriptor) {
descriptor.writable = false;
return descriptor;
}
class Example {
@readonly
method() {}
}
const obj = new Example();
obj.method = () => {}; // 报错:Cannot assign to read only property
属性装饰器
属性装饰器用于修饰类的属性,接收目标对象和属性名。
function logProperty(target: any, key: string) {
let value = target[key];
const getter = () => {
console.log(`Get ${key} => ${value}`);
return value;
};
const setter = (newVal: any) => {
console.log(`Set ${key} => ${newVal}`);
value = newVal;
};
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}
class User {
@logProperty
name: string;
}
const user = new User();
user.name = 'Alice'; // 输出:Set name => Alice
console.log(user.name); // 输出:Get name => Alice
参数装饰器
参数装饰器用于修饰方法的参数,接收目标对象、方法名和参数索引。
function validateParam(target: any, methodName: string, paramIndex: number) {
console.log(`Parameter ${paramIndex} of ${methodName} is decorated.`);
}
class Validator {
greet(@validateParam name: string) {}
}
// 输出:Parameter 0 of greet is decorated.
装饰器工厂
装饰器工厂是一个返回装饰器函数的函数,允许传递参数定制装饰器行为。
function log(message: string) {
return function (target: any, key: string, descriptor: PropertyDescriptor) {
console.log(`${message} - ${key} called.`);
return descriptor;
};
}
class Logger {
@log('DEBUG')
logMessage() {}
}
const logger = new Logger();
logger.logMessage(); // 输出:DEBUG - logMessage called.
注意事项
- 装饰器在 JavaScript 中尚未成为正式标准,需依赖编译工具支持。
- 装饰器执行顺序:参数装饰器 > 方法/属性装饰器 > 类装饰器(从内到外)。
- 避免在装饰器中直接修改原型链,可能导致不可预期的行为。
通过上述方法,可以灵活使用装饰器增强代码的可读性和功能性。







