JavaScript中的装饰器(Decorators)
字数 544 2025-11-07 22:15:36
JavaScript中的装饰器(Decorators)
装饰器是一种特殊类型的声明,用于修改类、方法、属性或参数的行为。它本质上是一个函数,通过@符号加函数名的语法形式,为被装饰的目标添加额外功能。
装饰器的基本概念
- 装饰器目前是ECMAScript的提案,需要Babel等工具转换才能使用
- 装饰器分为类装饰器、方法装饰器、属性装饰器、参数装饰器
- 装饰器执行时机是在代码编译时,而不是运行时
装饰器的基本语法结构
// 装饰器函数
function decorator(target, name, descriptor) {
// 装饰逻辑
}
// 使用装饰器
@decorator
class MyClass {
@decorator
myMethod() {}
}
类装饰器的实现步骤
- 类装饰器接收一个参数:被装饰的类构造函数
- 可以返回新的构造函数来替换原类
- 示例:为类添加静态属性
function addVersion(constructor) {
constructor.version = '1.0.0'
return constructor
}
@addVersion
class MyClass {}
console.log(MyClass.version) // 输出: 1.0.0
方法装饰器的详细实现
- 接收三个参数:目标类的原型、方法名、属性描述符
- 可以修改方法的行为,如添加日志、验证等
- 必须返回属性描述符对象
function log(target, name, descriptor) {
const originalMethod = descriptor.value
// 修改方法实现
descriptor.value = function(...args) {
console.log(`调用方法 ${name},参数:`, args)
const result = originalMethod.apply(this, args)
console.log(`方法 ${name} 执行结果:`, result)
return result
}
return descriptor
}
class Calculator {
@log
add(a, b) {
return a + b
}
}
const calc = new Calculator()
calc.add(2, 3) // 会输出调用日志
属性装饰器的应用
- 接收两个参数:目标类的原型、属性名
- 常用于元数据编程或属性验证
- 示例:自动将属性转为大写
function uppercase(target, propertyName) {
let value = target[propertyName]
// 定义getter和setter
const getter = () => value
const setter = (newVal) => {
value = newVal.toUpperCase()
}
// 重新定义属性
Object.defineProperty(target, propertyName, {
get: getter,
set: setter,
enumerable: true,
configurable: true
})
}
class Person {
@uppercase
name = 'john'
}
const person = new Person()
console.log(person.name) // 输出: JOHN
person.name = 'alice'
console.log(person.name) // 输出: ALICE
多个装饰器的执行顺序
- 装饰器从靠近目标的开始依次执行
- 执行顺序:从上到下,从内到外
- 示例演示执行顺序
function decoratorA(target, name, descriptor) {
console.log('执行装饰器A')
return descriptor
}
function decoratorB(target, name, descriptor) {
console.log('执行装饰器B')
return descriptor
}
class Example {
@decoratorA
@decoratorB
method() {}
}
// 执行顺序: 先B后A
实际应用场景
- 自动绑定this:解决类方法中this指向问题
function autoBind(target, name, descriptor) {
const originalMethod = descriptor.value
return {
configurable: true,
enumerable: false,
get() {
// 将方法绑定到当前实例
const boundFn = originalMethod.bind(this)
Object.defineProperty(this, name, {
value: boundFn,
configurable: true,
writable: true
})
return boundFn
}
}
}
- 参数验证装饰器
function validate(type) {
return function(target, name, descriptor) {
const originalMethod = descriptor.value
descriptor.value = function(...args) {
if (typeof args[0] !== type) {
throw new Error(`参数类型错误,期望${type}类型`)
}
return originalMethod.apply(this, args)
}
return descriptor
}
}
class Validator {
@validate('string')
process(text) {
return text.toUpperCase()
}
}
装饰器为JavaScript提供了强大的元编程能力,能够优雅地实现横切关注点(如日志、验证、性能监控等),使代码更加模块化和可维护。