js怎么实现装饰器
装饰器基础概念
装饰器是一种特殊类型的声明,能够被附加到类声明、方法、访问器、属性或参数上。装饰器使用@expression形式,expression求值后必须是一个函数,该函数会在运行时被调用,装饰器的声明信息作为参数传入。
实现方法装饰器
方法装饰器应用于方法的属性描述符,可以观察、修改或替换方法定义。方法装饰器接收三个参数:目标对象、属性名、属性描述符。
function log(target, name, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
console.log(`Calling ${name} with`, args);
return originalMethod.apply(this, args);
};
return descriptor;
}
class Calculator {
@log
add(a, b) {
return a + b;
}
}
实现类装饰器
类装饰器应用于类构造函数,可以用来观察、修改或替换类定义。类装饰器接收一个参数:类的构造函数。

function seal(constructor) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@seal
class MyClass {
method() {}
}
实现属性装饰器
属性装饰器应用于类的属性,接收两个参数:目标对象、属性名。属性装饰器不能直接修改属性的值,但可以通过返回属性描述符来影响属性的行为。
function readonly(target, propertyKey) {
const descriptor = {
writable: false
};
return descriptor;
}
class User {
@readonly
name = 'John';
}
实现参数装饰器
参数装饰器应用于构造函数或方法参数,接收三个参数:目标对象、方法名、参数索引。参数装饰器通常用于标记参数的特殊用途。

function validate(target, propertyKey, parameterIndex) {
// 添加元数据标记参数需要验证
}
class ApiService {
fetchData(@validate id) {
// 获取数据逻辑
}
}
装饰器工厂
装饰器工厂是一个返回装饰器函数的函数,允许通过参数配置装饰器行为。
function log(message) {
return function(target, propertyKey, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
console.log(message);
return originalMethod.apply(this, args);
};
return descriptor;
};
}
class Service {
@log('Executing process')
process() {
// 处理逻辑
}
}
注意事项
- 装饰器目前是ECMAScript提案,尚未成为正式标准
- TypeScript和Babel等工具提供了装饰器支持
- 装饰器执行顺序:参数装饰器 > 方法/访问器/属性装饰器 > 类装饰器
- 同一目标的多个装饰器按声明顺序从下到上执行
配置环境支持
在TypeScript中启用装饰器需要在tsconfig.json中设置:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
在Babel中需要安装@babel/plugin-proposal-decorators插件并在配置中启用:
{
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}






