装饰器

  1. function decorator(){
  2. }
  3. @decorator
  4. class Hd{
  5. }

这样子配置还是不行

  1. tsc -w

是通过tsconfig.json文件进行配置的,我们没有这个文件,所以我们得

  1. tsc --init

来创建一个tsconfig.json
tsconfig.json中开启experimentalDecoratorsemitDecoratorMetadata来开启这个新特性
之后的2.ts中报的错误会少点,就是缺少参数

  1. function decorator(target:object){
  2. }
  3. @decorator
  4. class Hd{
  5. }

我们这个时候去tsc -w就不报错了

类装饰器

  1. //坦克
  2. class Tank{
  3. //问题就是获取元素的坐标
  4. }
  5. //玩家
  6. class Player{
  7. }

碰到画布或者子弹游戏就结束,这样我们可以去定义一个装饰器;你要明白装饰器的定义就是一个函数

  1. //ClassDecorator: 定义一个class的装饰器
  2. const moveDecorator: ClassDecorator

进入ClassDecorator里面能看到:

  1. declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;

如果我们把装饰器放在

  1. @moveDecorator
  2. class Tank{
  3. }

target参数就是Tank;
如果我们把装饰器放在

  1. @moveDecorator
  2. class Player{
  3. }

target参数就是player

编译一下内容

  1. const moveDecorator: ClassDecorator = (target:object)=>{
  2. console.log(target)
  3. }
  4. @moveDecorator
  5. class Tank{
  6. }
  1. node 2.js

来运行,得到的结果

  1. [class Tank]
  1. const moveDecorator: ClassDecorator = (target:object)=>{
  2. console.log(target)
  3. //在原型对象上增加方法
  4. target.prototype.getPosition = ():{x:number,y:number} =>{
  5. return {x:100,y:200}
  6. }
  7. }
  8. class Tank{
  9. }
  10. const t = new Tank();
  11. console.log(t.getPosition())

错误先不管(ts报错,但是js还是会添加的)
运行js

  1. node 2.js

得到的结果:

  1. [class Tank]
  2. { x: 100, y: 200 }

报的错是类上没有这个属性,所以可以

  1. const moveDecorator: ClassDecorator = (target:Function)=>{
  2. console.log(target)
  3. //在原型对象上增加方法
  4. target.prototype.getPosition = ():{x:number,y:number} =>{
  5. return {x:100,y:200}
  6. }
  7. }
  8. @moveDecorator
  9. //坦克
  10. class Tank{
  11. public getPosition(){}
  12. }
  13. const t = new Tank();
  14. console.log(t.getPosition())

也可以:

  1. const moveDecorator: ClassDecorator = (target:Function)=>{
  2. console.log(target)
  3. //在原型对象上增加方法
  4. target.prototype.getPosition = ():{x:number,y:number} =>{
  5. return {x:100,y:200}
  6. }
  7. }
  8. @moveDecorator
  9. class Tank{
  10. }
  11. const t = new Tank();
  12. // console.log((<any>t).getPosition())
  13. console.log((t as any).getPosition())

你也可以在原型对象上添加一个name的属性,装饰器和继承都是对原型对象进行操作。

装饰器decorator语法糖

  1. const moveDecorator: ClassDecorator = (target:Function)=>{
  2. console.log(target)
  3. //在原型对象上增加方法
  4. target.prototype.getPosition = ():{x:number,y:number} =>{
  5. return {x:100,y:200}
  6. }
  7. }
  8. class Tank{}
  9. const t = new Tank()
  10. moveDecorator(Tank)

输出结构与

  1. const moveDecorator: ClassDecorator = (target:Function)=>{...}
  2. @moveDecorator
  3. class Tank{}
  4. const t = new Tank()
  5. console.log((t as any).getPosition())

是一致的

装饰器的叠加

  1. const moveDecorator: ClassDecorator = (target:Function)=>{
  2. console.log(target)
  3. //在原型对象上增加方法
  4. target.prototype.getPosition = ():{x:number,y:number} =>{
  5. return {x:100,y:200}
  6. }
  7. }
  8. const MusicDecoator:ClassDecorator = (target:Function) =>{
  9. target.prototype.playMusic = ():void =>{
  10. console.log('播放音乐')
  11. }
  12. }
  13. @moveDecorator
  14. @MusicDecoator
  15. class Player{
  16. }
  17. const p = new Player()
  18. console.log((p as any).playMusic())

产生的结果:

  1. [class Player]
  2. 播放音乐
  3. undefined

通过装饰器实现统一消息响应