JavaScript中的装饰器(Decorators)
字数 544 2025-11-07 22:15:36

JavaScript中的装饰器(Decorators)

装饰器是一种特殊类型的声明,用于修改类、方法、属性或参数的行为。它本质上是一个函数,通过@符号加函数名的语法形式,为被装饰的目标添加额外功能。

装饰器的基本概念

  1. 装饰器目前是ECMAScript的提案,需要Babel等工具转换才能使用
  2. 装饰器分为类装饰器、方法装饰器、属性装饰器、参数装饰器
  3. 装饰器执行时机是在代码编译时,而不是运行时

装饰器的基本语法结构

// 装饰器函数
function decorator(target, name, descriptor) {
  // 装饰逻辑
}

// 使用装饰器
@decorator
class MyClass {
  @decorator
  myMethod() {}
}

类装饰器的实现步骤

  1. 类装饰器接收一个参数:被装饰的类构造函数
  2. 可以返回新的构造函数来替换原类
  3. 示例:为类添加静态属性
function addVersion(constructor) {
  constructor.version = '1.0.0'
  return constructor
}

@addVersion
class MyClass {}

console.log(MyClass.version) // 输出: 1.0.0

方法装饰器的详细实现

  1. 接收三个参数:目标类的原型、方法名、属性描述符
  2. 可以修改方法的行为,如添加日志、验证等
  3. 必须返回属性描述符对象
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) // 会输出调用日志

属性装饰器的应用

  1. 接收两个参数:目标类的原型、属性名
  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

多个装饰器的执行顺序

  1. 装饰器从靠近目标的开始依次执行
  2. 执行顺序:从上到下,从内到外
  3. 示例演示执行顺序
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

实际应用场景

  1. 自动绑定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
    }
  }
}
  1. 参数验证装饰器
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提供了强大的元编程能力,能够优雅地实现横切关注点(如日志、验证、性能监控等),使代码更加模块化和可维护。

JavaScript中的装饰器(Decorators) 装饰器是一种特殊类型的声明,用于修改类、方法、属性或参数的行为。它本质上是一个函数,通过@符号加函数名的语法形式,为被装饰的目标添加额外功能。 装饰器的基本概念 装饰器目前是ECMAScript的提案,需要Babel等工具转换才能使用 装饰器分为类装饰器、方法装饰器、属性装饰器、参数装饰器 装饰器执行时机是在代码编译时,而不是运行时 装饰器的基本语法结构 类装饰器的实现步骤 类装饰器接收一个参数:被装饰的类构造函数 可以返回新的构造函数来替换原类 示例:为类添加静态属性 方法装饰器的详细实现 接收三个参数:目标类的原型、方法名、属性描述符 可以修改方法的行为,如添加日志、验证等 必须返回属性描述符对象 属性装饰器的应用 接收两个参数:目标类的原型、属性名 常用于元数据编程或属性验证 示例:自动将属性转为大写 多个装饰器的执行顺序 装饰器从靠近目标的开始依次执行 执行顺序:从上到下,从内到外 示例演示执行顺序 实际应用场景 自动绑定this:解决类方法中this指向问题 参数验证装饰器 装饰器为JavaScript提供了强大的元编程能力,能够优雅地实现横切关注点(如日志、验证、性能监控等),使代码更加模块化和可维护。