装饰器

(Decorators)是一种特殊类型的声明,它可以被附加到类声明,方法,属性或参数上。

装饰器由@符号紧接一个函数名称,如@expression,expression求值后必须是一个函数, 
在函数执行的时候装饰器的声明方法会被执行。

装饰器是用来给附着的主体进行装饰,添加额外行为的。 
感觉typescript的装饰器就是Java的注解,'C#'的特性,算是一种元编程,
定义在对象上,用于代码执行前后,做额外的事情,主要提供面向截面编程。 

TypeScript官方介绍:
装饰器(Decorators)为我们在类的声明及成员上通过元编程语法添加标注提供了一种方式。 
Javascript里的装饰器目前处在建议征集的第一阶段,但在TypeScript里已做为一项实验性特性予以支持。 
注意:装饰器是一项实验性特性,在未来的版本中可能会发生改变。 
若要启用实验性的装饰器特性,你必须在命令行或tsconfig.json里启用experimentalDecorators编译器
选项: 
命令行: tsc --target ES5 --experimentalDecorators 
tsconfig.json文件启用: 
{ 
    "compilerOptions": { 
        "target": "ES5", 
        "experimentalDecorators": true 
    }
} 
装饰器求值:
    类中不同声明的装饰器将按以下规定的顺序应用: 
    1.参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个实例成员。 
    2.参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰其应用到每个静态成员。 
    3.参数装饰器应用到构造函数。 
    4.类装饰器应用到类。 
类装饰器:
    1.在类声明之前声明,类装饰器应用于类的构造函数,可以用来监视,修改或替换类定义。 
    重点1:类装饰器表达式会在运行时当做函数被调用,类的构造函数被当做其唯一的参数。 
    重点2:如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
    (也就是说,可以用类装饰器返回一个函数的形式来动态替换类的原本构造函数)。
    
注意: 如: 
    @sealed 
    class Greeter{ 
        greeter:string; 
        constructor(message:string){ 
            this.greeter=message; 
        } 
        greeter(){ 
            return "hello"+this.greeter; 
        } 
    } 
   //@sealed装饰器定义如下 
   function sealed(constructor:Function){ 
        Object.seal(constructor); 
        Object.seal(constructor.protected); 
        //当@sealed被执行时它将密封该了类的构造函数和原型。 
    } 
方法装饰器:
    声明在一个方法的声明之前,它会被用到方法的属性描述符上(descriptor),
可以用来监视,修改或替换方法定义。
    方法装饰器不能用在声明文件(.d.ts), 重载或者任何外部上下(比如declare的类中)中。 
    方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数: 
    1.target:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。 
    2.propertyKey:方法(成员)的名称。 
    3.descriptor:成员的属性描述符。 
    注意:
        如果代码的输出版本小于ES5,属性描述符将会是undefined。 
        如果方法装饰器的返回一个值,它会被用作方法的属性描述符,如果代码的输出目标小于ES5,
    返回值会被忽略。
        其中descriptor类型为TypedPropertyDescriptor, 在typescript中定义如下: 

interface TYpedPropertyDescriptor { 
      enumerable?:boolean; //是否可遍历
      configurable?:boolean; //属性描述是否可改变或者属性是否可删除 
      writable?:boolean; //是否可修改 
      value?:T; //属性的值 
      get?:()=>T; //属性的访问器函数(getter) 
      set?:(value:T)=>void //属性的设置器函数 
} 
如:
class TestClass{ 
    @log 
    testMethod(arg:string){ 
        return "xzm:"+arg; 
    } 
}
//装饰器@log的实现: 
function log(
  target:Object,
  properrtyKey:string,
  descriptor:TypedPropertyDescriptor 
){ 
  let origin=descriptor.value; //通过方法属性描述符的value属性,取得有关方法对象 
  descriptor.value=function(...args:any[]){       
    console.log("args:"+JSON.stringify(args)); //调用前
    let result=origin.apply(this,args); //调用方法         
    console.log("The result" + result); 
    return result; 
  } 
  return descriptor; 
} 
  //使用代码测试: 
  new TestClass().testMethod("test method descorator"); 
  //结果输出如下: 
  //agrs:["test method descorator"] 
  //The result-xzm:test method descorator 

访问器装饰器:
访问器装饰器声明在一个访问器声明之前。
访问器装饰器应用于访问器的属性描述符(),并且可以用来监视,修改或替换一个访问器定义。 
注意:
    TypeScript不允许同时装饰一个成员的set或者get访问器。
    取而代之的是,一个成员的所有装饰必须应用在文档顺序的第一个访问器上。
    这是因为, 在装饰器应用于一个属性描述符时,它联合了get和set访问器,而不是分开声明的。 
    访问器装饰器表达式会在运行时当做函数被调用,传入下列3个参数: 
    1.target:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
    2.properrtyKey:方法(成员)的名称。 
    3.descriptor:成员的属性描述符。 访问器装饰器基本和方法装饰器一样,
    除了需要注意上面提到的不允许同时装饰一个成员的set和get访问器以外。 

属性装饰器:
    属性装饰器声明在一个属性声明之前,属性装饰器表达式会在运行时当做函数被调用,传入下列两个参数:
    1.target:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。 
    2.property:成员(属性)的名字。 
    注意:属性描述符不会作为参数传入属性装饰器,这于TypeScript是如何初始化属性装饰器有关。
    因为目前没有办法在顶一个原型对象的成员时描述一个实例的属性, 并且没办法监视或修改一个属性的
初始化方法。因此属性描述符只能用来监视类中是否声明了某个名字的属性。 

参数装饰器:
    声明在一个参数声明之前(用于的类的构造函数或方法声明),参数装饰器表达式会在运行是被当做函数调用
    1.target:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。 
    2.propertyKey:成员的名字。 
    3.parameterIndex:参数在函数参数列表中的索引。 注意:参数装饰器只能用来监视一个方法的参数
是否被传入。
    参数装饰器在Angular中被广泛使用,特别是结合reflect-metadata库来支持实验性的Metadata 
API。 
    参数装饰器的返回值会被忽略。 
装饰器组合:
    TypeScript支持多个装饰器同时应用到一个声明上,实现多个装饰器复合使用,语法支持从左到右,
或从上到下书写。
    在TypeScript里,当多个装饰器应用在一个声明上的时候,会进行如下步骤的操作: 
    1.从左到右(从上到下)依次执行装饰器函数,得到返回结果。 
    2.返回的结果会被当做函数,从左到右(从上倒下)依次调用。

摘自 https://www.aliyun.com/jiaocheng/812629.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,692评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,482评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,995评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,223评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,245评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,208评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,091评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,929评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,346评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,570评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,739评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,437评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,037评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,677评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,833评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,760评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,647评论 2 354