js装饰器急速入门

267 阅读1分钟

前言

装饰器是 JavaScript 中一个非常强大的特性,它允许你在不修改原有函数或类的情况下,为它们添加新的功能

上代码!

(●'◡'●)

正文

1. 函数装饰器

函数装饰器可以用来修改函数的行为。

// 定义一个装饰器函数
function logDecorator(targetFn) {
  // 返回一个新的函数,这个新函数会替换原来的函数
  return function(...args) {
    // 注意:此处的【...args】其实就是targetFn的入参!!
    console.log(`调用了函数 ${targetFn.name},参数是:`, args);
    // 调用原始的函数
    return targetFn(...args);
  };
}

// 使用装饰器
const add = logDecorator(function(a, b) {
  return a + b;
});

// 调用装饰后的函数
console.log(add(3, 4)); // 输出:调用了函数 ƒ,参数是: [3, 4],然后输出 7

说明

  • logDecorator 是一个装饰器函数,它接收一个函数 targetFn 作为参数。
  • 装饰器返回一个新的函数,这个新函数在调用时会先打印日志,然后调用原始的 targetFn
  • 这个虽然不像装饰器,但真的是装饰器

2. 类装饰器

类装饰器可以用来修改类的行为。

// 定义一个类装饰器
function logClass(targetClass) {
  // 返回一个新的类,这个新类会替换原来的类
  return class extends targetClass {
    constructor(...args) {
      console.log(`创建了一个 ${targetClass.name} 实例,参数是:`, args);
      super(...args);
    }
  };
}

// 使用装饰器
@logClass
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

// 创建实例
const person = new Person('Alice', 25);
// 输出:创建了一个 Person 实例,参数是: [ 'Alice', 25 ]

说明

  • @logClass 是一个类装饰器,它接收一个类 targetClass 作为参数。
  • 装饰器返回一个新的类,这个新类在创建实例时会先打印日志,然后调用原始类的构造函数。

3. 方法装饰器

方法装饰器可以用来修改类中的方法。

// 定义一个方法装饰器
function logMethod(target, propertyKey, descriptor) {
  // 获取原始的方法
  const originalMethod = descriptor.value;

  // 替换原始的方法
  descriptor.value = function(...args) {
    console.log(`调用了方法 ${propertyKey},参数是:`, args);
    // 调用原始的方法
    return originalMethod.apply(this, args);
  };
}

// 使用装饰器
class Calculator {
  @logMethod
  add(a, b) {
    return a + b;
  }
}

// 创建实例并调用方法
const calc = new Calculator();
console.log(calc.add(5, 6)); // 输出:调用了方法 add,参数是: [5, 6],然后输出 11

说明

  • @logMethod 是一个方法装饰器,它接收三个参数:
    • target:类的原型或类本身。
    • propertyKey:方法的名称。
    • descriptor:方法的描述符,包含原始方法的引用。
  • 装饰器通过修改 descriptor.value 来替换原始方法。

4. 属性装饰器

属性装饰器可以用来修改类中的属性。

// 定义一个属性装饰器
function logProperty(target, propertyKey) {
  let value = target[propertyKey];

  // 替换属性的 getter 和 setter
  Object.defineProperty(target, propertyKey, {
    get: function() {
      console.log(`获取属性 ${propertyKey}`);
      return value;
    },
    set: function(newValue) {
      console.log(`设置属性 ${propertyKey}${newValue}`);
      value = newValue;
    }
  });
}

// 使用装饰器
class User {
  @logProperty
  name = 'Alice';
}

// 创建实例并操作属性
const user = new User();
console.log(user.name); // 输出:获取属性 name,然后输出 Alice
user.name = 'Bob'; // 输出:设置属性 name 为 Bob
console.log(user.name); // 输出:获取属性 name,然后输出 Bob

说明

  • @logProperty 是一个属性装饰器,它接收两个参数:
    • target:类的原型或类本身。
    • propertyKey:属性的名称。
  • 装饰器通过 Object.defineProperty 修改属性的 getter 和 setter。

最后

建议在项目中使用起来

下次见(●'◡'●)!