类装饰器

//类装饰器
namespace a {
  function addNameEat(constructor: Function) {
      constructor.prototype.name = 'zhufeng';
      constructor.prototype.eat = function () { }
  }
  @addNameEat
  class Person {
      name: string;
      eat: Function;
      constructor() { }
  }
  let p: Person = new Person();
  console.log(p.name);
  p.eat();
}
//类装饰器工厂
namespace b {
  function addNameEatFactory(name: string) {
      return function addNameEat(x: Function) {
          x.prototype.name = name;
          x.prototype.eat = function () { }
      }
  }
  @addNameEatFactory('jiagou')
  class Person {
      name: string;
      eat: Function;
      constructor() { }
  }
  let p: Person = new Person();
  console.log(p.name);
  p.eat();
}
// 类型安全
namespace c {
  function replaceClass(constructor: Function) {
      return class {
          name: string;
          eat: Function;
          age: number; // 属性可以多,但不能少
          constructor() { }
      }
  }
  @replaceClass
  class Person {
      name: string;
      eat: Function;
      constructor() { }
  }
  let p: Person = new Person();
  console.log(p.name);
  p.eat();
}

属性装饰器

// 属性装饰器:装饰属性、装饰方法
namespace d {
    // 如果装饰的是实例属性的话,target 是构造函数的原型
    function upperCase(target: any, propertyKey: string) {
        let value = target[propertyKey];
        if (delete target[propertyKey]) {
            Object.defineProperty(target, propertyKey, {
                get: () => value,
                set: (newVal: string) => { value = newVal.toUpperCase() },
                enumerable: true,
                configurable: true
            });
        }
    }
    // 如果装饰的是静态属性的话,target 是构造函数本身
    function staticPropertyDecorator(target: any, propertyKey: string) {
        console.log(target, propertyKey);
    }
    function noEnumerable(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        console.log(target);
        console.log(propertyKey);
        descriptor.enumerable = false;
    }
    function toNumber(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        let oldMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            args = args.map(item => parseFloat(item));
            return oldMethod.apply(this, args);
        }
    }
    class Person {
        @upperCase
        name: string = 'zhangsan'; //实例属性
        @staticPropertyDecorator
        static age: number = 10; //静态属性
        @noEnumerable
        getName() { console.log(this.name); }//实例方法
        @toNumber
        sum(...args: any[]) {//实例方法
            return args.reduce((accu: number, item: number) => accu + item, 0);
        }
    }
    let p = new Person();
    console.log(p.name);
    console.log(p.sum('1', '2', '3'));
}

参数装饰器

namespace e {
    // 在 IOC 容器里大放异彩  Nest.js 大量的用到了参数装饰器
    // 参数列表:静态成员就是构造函数,非静态成员就是构造函数原型、方法的名称、参数的索引
    function addAge(target: any, methodName, paramIndex: number) {
        console.log(target, methodName, paramIndex);
        target.age = 10;
    }
    class Person {
        age: number;
        login(username: string, @addAge password: string) {
            console.log(this.age, username, password);
        }
    }
    let p = new Person();
    p.login('1', '2');
}

装饰器的执行顺序

/**
 * 装饰器执行顺序的规律(一般从内往外执行 先内后外)
 * 1.类装饰器是最后执行的,后写的类装饰器先执行
 * 2.方法和方法参数中的装饰器先执行参数
 * 3.方法和属性装饰器,谁在前面先执行谁
 */
namespace f {
    function ClassDecorator1() {
        return function (target) {
            console.log('ClassDecorator1');
        }
    }
    function ClassDecorator2() {
        return function (target) {
            console.log('ClassDecorator2');
        }
    }
    function PropertyDecorator(name: string) {
        return function (target, propertyName) {
            console.log('PropertyDecorator', propertyName, name);
        }
    }
    function MethodDecorator() {
        return function (target, propertyName) {
            console.log('MethodDecorator', propertyName);
        }
    }
    function ParameterDecorator() {
        return function (target, methodName, index) {
            console.log('ParameterDecorator', methodName, index);
        }
    }
    @ClassDecorator1()
    @ClassDecorator2()
    class Person {
        @PropertyDecorator('name')
        name: string = '';
        @PropertyDecorator('age')
        age: number = 10;
        @MethodDecorator()
        hello(@ParameterDecorator() p1: string, @ParameterDecorator() p2: string) { }
    }
}

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于产品、设计、开发的问题和看法,还有技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程

了解更多

目录

  1. 1. 类装饰器
  2. 2. 属性装饰器
  3. 3. 参数装饰器
  4. 4. 装饰器的执行顺序