typescript 深入理解装饰器

安装

// cmd
cnpm i -g typescript

配置

// cmd
tsc --init

将tsconfig.json的experimentalDecorators设为true, 启动实验阶段的装饰器功能

代码

新建文件test.ts

// 装饰器调用顺序
// 属性装饰器>方法参数装饰器>方法装饰器>静态属性装饰器>静态方法装饰器>类装饰器
// 定义:相同装饰器按右边>左边 ,下面>上面
// 执行:相同装饰器按左边>右边 ,上面>下面

/**
 * 属性装饰器
 * @param targetPrototype 构造函数的原型
 * @param propName 属性名称
 */
function propDecorator1(targetPrototype: any, propName: string) {
  console.log('属性装饰器1:', targetPrototype, propName);
}

function propDecorator2(params: string) {
  console.log('属性装饰器2 before:', params);
  return function (targetPrototype: any, propName: string) {
    // targetPrototype[propName]是在原型链上查找实例属性,永远为undefined
    console.log('属性装饰器2:', targetPrototype, propName, targetPrototype[propName]);
    targetPrototype[propName] = "会在原型上面添加该属性并赋值,不是实例对象";
  };
}

function propDecorator3(params: string) {
  console.log('属性装饰器3 before:', params);
  return function (targetPrototype: any, propName: string) {
    console.log('属性装饰器3:', targetPrototype, propName);
  };
}

/**
 * 方法装饰器
 * @param targetPrototype 构造函数的原型
 * @param methodName 方法名称
 * @param descr 方法的描述
 */
function methodDecorator1(targetPrototype: any, methodName: string, descriptor: PropertyDescriptor) {
  console.log('方法装饰器1:', targetPrototype, methodName, descriptor);
}

let methodDecorator2: any = function (params: string) {
  console.log('方法装饰器2 before:', params);
  return function (targetPrototype: any, methodName: string, descriptor: PropertyDescriptor) {
    console.log('方法装饰器2:', targetPrototype, methodName, descriptor);
  };
};

let methodDecorator3: any = function (params: string) {
  console.log('方法装饰器3 before:', params);
  return function (targetPrototype: any, methodName: string, descriptor: PropertyDescriptor) {
    console.log('方法装饰器3:', targetPrototype, methodName, descriptor);
    let originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
      args = args.map(item => item += " test");
      return originalMethod.apply(this, args);
    };
    return descriptor;
  };
};

/**
 * 方法参数装饰器
 * @param targetPrototype 构造函数的原型
 * @param methodName 方法名称
 * @param paramIndex 参数在arguments中的下标
 */
function paramDecorator1(targetPrototype: any, methodName: string, paramIndex: number) {
  console.log('方法参数装饰器1:', targetPrototype, methodName, paramIndex);
}

function paramDecorator2(params: string) {
  console.log('方法参数装饰器2 before:', params);
  return function (targetPrototype: any, methodName: string, paramIndex: number) {
    console.log('方法参数装饰器2:', targetPrototype, methodName, paramIndex);
  };
}

function paramDecorator3(params: string) {
  console.log('方法参数装饰器3 before:', params);
  return function (targetPrototype: any, methodName: string, paramIndex: number) {
    console.log('方法参数装饰器3:', targetPrototype, methodName, paramIndex);
  };
}

/**
 * 静态属性修饰器
 * @param targetPrototype
 * @param propName
 */
function staticPropDecorator(param: string) {
  console.log('静态属性修饰器 before:', param);
  return function (targetPrototype: any, propName: string) {
    console.log('静态属性修饰器:', targetPrototype, propName, targetPrototype[propName]);
    targetPrototype[propName]="静态属性初始值被修改了!";
  }
}

/**
 * 静态方法修饰器
 * @param targetPrototype
 * @param methodName
 * @param descriptor
 */
function staticMethodDecorator(param: string) {
  console.log('静态方法修饰器 before:', param);
  return function (targetPrototype: any, methodName: string, descriptor: PropertyDescriptor) {
    console.log('静态方法修饰器:', targetPrototype, methodName, descriptor);
  }
}

/**
 * 类装饰器
 * @param targetClass
 */
function classDecorator1(constructor: Function) {
  console.log('类装饰器1:', constructor);
}

function classDecorator2(params: string) {
  console.log('类装饰器2 before:', params);
  return function (constructor: Function) {
    console.log('类装饰器2:', constructor);
  };
}

function classDecorator3(params: string) {
  console.log('类装饰器3 before:', params);
  return function (constructor: Function) {
    console.log('类装饰器3:', constructor);
  };
}

@classDecorator1
@classDecorator2('params2')
@classDecorator3('params3')
class Test {
  @propDecorator1
  @propDecorator2('param2')
  @propDecorator3('param3')
  public msg: string = "属性初始值";

  @staticPropDecorator('静态属性')
  static title: string = "静态属性初始值";


  constructor(msg: string) {
    this.msg = msg;
  }

  @methodDecorator1
  @methodDecorator2('param2')
  @methodDecorator3('param3')
  toString(@paramDecorator1 str1: string, @paramDecorator2('param2') str2: string, @paramDecorator3('param3') str3: string) {
    console.log('toString:', str1, str2, str3);
  }

  @staticMethodDecorator('静态方法')
  static staticToString() {
    console.log(this.title);
  }
}

let t:any = new Test('this is a msg.');
t.toString("ss", "dd", "ff");//methodDecorator3装饰器对该方法进行了重写
console.log(t.msg, t.__proto__.msg);
Test.staticToString();

运行

//cmd
tsc test --target ES5 --experimentalDecorators
node test

结果

属性装饰器2 before: param2
属性装饰器3 before: param3
属性装饰器3: Test { toString: [Function] } msg
属性装饰器2: Test { toString: [Function] } msg undefined
属性装饰器1: Test { toString: [Function], msg: '会在原型上面添加该属性并赋值,不是实例对象' } msg
方法装饰器2 before: param2
方法装饰器3 before: param3
方法参数装饰器2 before: param2
方法参数装饰器3 before: param3
方法参数装饰器3: Test { toString: [Function], msg: '会在原型上面添加该属性并赋值,不是实例对象' } toString 2
方法参数装饰器2: Test { toString: [Function], msg: '会在原型上面添加该属性并赋值,不是实例对象' } toString 1
方法参数装饰器1: Test { toString: [Function], msg: '会在原型上面添加该属性并赋值,不是实例对象' } toString 0
方法装饰器3: Test { toString: [Function], msg: '会在原型上面添加该属性并赋值,不是实例对象' } toString { value: [Function],
  writable: true,
  enumerable: true,
  configurable: true }
方法装饰器2: Test { toString: [Function], msg: '会在原型上面添加该属性并赋值,不是实例对象' } toString { value: [Function],
  writable: true,
  enumerable: true,
  configurable: true }
方法装饰器1: Test { toString: [Function], msg: '会在原型上面添加该属性并赋值,不是实例对象' } toString { value: [Function],
  writable: true,
  enumerable: true,
  configurable: true }
静态属性修饰器 before: 静态属性
静态属性修饰器: function Test(msg) {
        this.msg = "属性初始值";
        this.msg = msg;
    } title 静态属性初始值
静态方法修饰器 before: 静态方法
静态方法修饰器: function Test(msg) {
        this.msg = "属性初始值";
        this.msg = msg;
    } staticToString { value: [Function],
  writable: true,
  enumerable: true,
  configurable: true }
类装饰器2 before: params2
类装饰器3 before: params3
类装饰器3: function Test(msg) {
        this.msg = "属性初始值";
        this.msg = msg;
    }
类装饰器2: function Test(msg) {
        this.msg = "属性初始值";
        this.msg = msg;
    }
类装饰器1: function Test(msg) {
        this.msg = "属性初始值";
        this.msg = msg;
    }
toString: ss test dd test ff test
this is a msg. 会在原型上面添加该属性并赋值,不是实例对象
静态属性初始值被修改了!

typescript装饰器官方中文文档

欢迎讨论,觉得有用的点个赞呗 ~ +_+ ~

发布了38 篇原创文章 · 获赞 66 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/lyt_angularjs/article/details/101061998