摘要:本文從裝飾模式出發(fā),聊聊中的裝飾器和注解。該函數(shù)的函數(shù)名。不提供元數(shù)據(jù)的支持。中的元數(shù)據(jù)操作可以通過(guò)包來(lái)實(shí)現(xiàn)對(duì)于元數(shù)據(jù)的操作。
??隨著Typescript的普及,在KOA2和nestjs等nodejs框架中經(jīng)??吹筋愃朴趈ava spring中注解的寫法。本文從裝飾模式出發(fā),聊聊Typescipt中的裝飾器和注解。
什么是裝飾者模式
Typescript中的裝飾器
Typescript中的注解
總結(jié)
原文地址:https://github.com/forthealll...
歡迎star
一、什么是裝飾者模式??最近在看nestjs等支持Typescript的node框架,經(jīng)??吹竭@樣一種寫法:
import { Controller, Get } from "@nestjs/common"; @Controller("cats") export class CatsController { @Get() findAll() { return "This action returns all cats"; } }
??上述代碼定義了一個(gè)處理url為“/cats”的控制器,該控制器對(duì)于url為“/cats”的get方法執(zhí)行findAll()函數(shù),返回相應(yīng)的字符串。
??在上述的代碼中,用@Controller("cats")修飾CatsController類,通過(guò)@Get來(lái)修飾類中的findAll方法,這就是典型的裝飾者模式。通過(guò)@Controller("cats")和@Get修飾后的類CatsController,簡(jiǎn)單來(lái)說(shuō),就是擁有了豐富的“內(nèi)涵”。
下面看看具體裝飾者模式的定義:
我們知道繼承模式是豐富子元素“內(nèi)涵”的一種重要方式,不管是繼承接口還是子類繼承基類。而裝飾者模式可以在不改變繼承關(guān)系的前提下,包裝先有的模塊,使其內(nèi)涵更加豐富,并不會(huì)影響到原來(lái)的功能。與繼承相比,更加的靈活。
javascript中的裝飾器處于建議征集的第二階段,通過(guò)babel和Typescrit都可以實(shí)現(xiàn)裝飾器的語(yǔ)法。
二、Typescript中的裝飾器Typescript中的裝飾器與類相關(guān),分別可以修飾類的實(shí)例函數(shù)和靜態(tài)函數(shù)、類本身、類的屬性、類中函數(shù)的參數(shù)以及類的set/get存取器,下面來(lái)意義介紹。
(1)、類方法的裝飾器下面來(lái)介紹一下用裝飾器來(lái)修飾函數(shù),首先來(lái)看一個(gè)例子:
let temple; function log(target, key, descriptor) { console.log(`${key} was called!`); temple = target; } class P { @log foo() { console.log("Do something"); } } const p = new P() p.foo() console.log(P.prototype === temple) //true
上述是實(shí)例方法foo中我們用log函數(shù)修飾,log函數(shù)接受三個(gè)參數(shù),通過(guò)P.prototype === temple(target)可以判斷,在類的實(shí)例函數(shù)的裝飾器函數(shù)第一個(gè)參數(shù)為類的原型,第二個(gè)參數(shù)為函數(shù)名本身,第三個(gè)參數(shù)為該函數(shù)的描述屬性。
具體總結(jié)如下,對(duì)于類的函數(shù)的裝飾器函數(shù),依次接受的參數(shù)為:
target:如果修飾的是類的實(shí)例函數(shù),那么target就是類的原型。如果修飾的是類的靜態(tài)函數(shù),那么target就是類本身。
key: 該函數(shù)的函數(shù)名。
descriptor:該函數(shù)的描述屬性,比如 configurable、value、enumerable等。
從上述的例子中我們可以看到,用裝飾器來(lái)修飾相應(yīng)的類的函數(shù)十分方便:
@log foo() { ... }(2)、類的裝飾器
裝飾函數(shù)也可以直接修飾類:
let temple function foo(target){ console.log(target); temple = target } @foo class P{ constructor(){ } } const p = new P(); temple === P //true
當(dāng)裝飾函數(shù)直接修飾類的時(shí)候,裝飾函數(shù)接受唯一的參數(shù),這個(gè)參數(shù)就是該被修飾類本身。上述的例子中,輸出的target就是類P的本身。
此外,在修飾類的時(shí)候,如果裝飾函數(shù)有返回值,該返回值會(huì)重新定義這個(gè)類,也就是說(shuō)當(dāng)裝飾函數(shù)有返回值時(shí),其實(shí)是生成了一個(gè)新類,該新類通過(guò)返回值來(lái)定義。
舉例來(lái)說(shuō):
function foo(target){ return class extends target{ name = "Jony"; sayHello(){ console.log("Hello "+ this.name) } } } @foo class P{ constructor(){ } } const p = new P(); p.sayHello(); // 會(huì)輸出Hello Jony
上面的例子可以看到,當(dāng)裝飾函數(shù)foo有返回值時(shí),實(shí)際上P類已經(jīng)被返回值所代表的新類所代替,因此P的實(shí)例p擁有sayHello方法。
(3)、類的屬性的裝飾器下面我們來(lái)看類的屬性的裝飾器,裝飾函數(shù)修飾類的屬性時(shí),在類實(shí)例化的時(shí)候調(diào)用屬性的裝飾函數(shù),舉例來(lái)說(shuō):
function foo(target,name){ console.log("target is",target); console.log("name is",name) } class P{ @foo name = "Jony" } const p = new P(); //會(huì)依次輸出 target is f P() name is Jony
這里對(duì)于類的屬性的裝飾器函數(shù)接受兩個(gè)參數(shù),對(duì)于靜態(tài)屬性而言,第一個(gè)參數(shù)是類本身,對(duì)于實(shí)例屬性而言,第一個(gè)參數(shù)是類的原型,第二個(gè)參數(shù)是指屬性的名字。
(4)、類函數(shù)參數(shù)的裝飾器接著來(lái)看類函數(shù)參數(shù)的裝飾器,類函數(shù)的參數(shù)裝飾器可以修飾類的構(gòu)建函數(shù)中的參數(shù),以及類中其他普通函數(shù)中的參數(shù)。該裝飾器在類的方法被調(diào)用的時(shí)候執(zhí)行,下面來(lái)看實(shí)例:
function foo(target,key,index){ console.log("target is",target); console.log("key is",key); console.log("index is",index) } class P{ test(@foo a){ } } const p = new P(); p.test("Hello Jony") // 依次輸出 f P() , test , 0
類函數(shù)參數(shù)的裝飾器函數(shù)接受三個(gè)參數(shù),依次為類本身,類中該被修飾的函數(shù)本身,以及被修飾的參數(shù)在參數(shù)列表中的索引值。上述的例子中,會(huì)依次輸出 f P() 、test和0。再次明確一下修飾函數(shù)參數(shù)的裝飾器函數(shù)中的參數(shù)含義:
target: 類本身
key:該參數(shù)所在的函數(shù)的函數(shù)名
index: 該參數(shù)在函數(shù)參數(shù)列表中的索引值
從上面的Typescrit中在基類中常用的裝飾器后,我們發(fā)現(xiàn):
裝飾器可以起到分離復(fù)雜邏輯的功能,且使用上極其簡(jiǎn)單方便。與繼承相比,也更加靈活,可以從裝飾類,到裝飾類函數(shù)的參數(shù),可以說(shuō)武裝到了“牙齒”。
三、Typescript中的注解在了解了Typescrit中的裝飾器之后,接著我們來(lái)看Typescrit中的注解。
什么是注解,所謂注解的定義就是:
為相應(yīng)的類附加元數(shù)據(jù)支持。
所謂元數(shù)據(jù)可以簡(jiǎn)單的解釋,就是修飾數(shù)據(jù)的數(shù)據(jù),比如一個(gè)人有name,age等數(shù)據(jù)屬性,那么name和age這些字段就是為了修飾數(shù)據(jù)的數(shù)據(jù),可以簡(jiǎn)單的稱為元數(shù)據(jù)。
元數(shù)據(jù)簡(jiǎn)單來(lái)說(shuō)就是可以修飾某些數(shù)據(jù)的字段。下面給出裝飾器和注解的解釋和區(qū)別:
裝飾器:定義劫持,可以對(duì)類,類的方法,類的屬性以及類的方法的入?yún)⑦M(jìn)行修改。不提供元數(shù)據(jù)的支持。
注解:僅提供元數(shù)據(jù)的支持。
兩者之間的聯(lián)系:
通過(guò)注解添加元數(shù)據(jù),然后在裝飾器中獲取這些元數(shù)據(jù),完成對(duì)類、類的方法等等的修改,可以在裝飾器中添加元數(shù)據(jù)的支持,比如可以可以在裝飾器工廠函數(shù)以及裝飾器函數(shù)中添加元數(shù)據(jù)支持等。
(1)、Typescript中的元數(shù)據(jù)操作可以通過(guò)reflect-metadata包來(lái)實(shí)現(xiàn)對(duì)于元數(shù)據(jù)的操作。首先我們來(lái)看reflect-metadata的使用,首先定義使用元數(shù)據(jù)的函數(shù):
const formatMetadataKey = Symbol("format"); function format(formatString: string) { return Reflect.metadata(formatMetadataKey, formatString); } function getFormat(target: any, propertyKey: string) { return Reflect.getMetadata(formatMetadataKey, target, propertyKey); }
這里的format可以作為裝飾器函數(shù)的工廠函數(shù),因?yàn)閒ormat函數(shù)返回的是一個(gè)裝飾器函數(shù),上述的方法定義了元數(shù)據(jù)Sysmbol("format"),用Sysmbol的原因是為了防止元數(shù)據(jù)中的字段重復(fù),而format定義了取元數(shù)據(jù)中相應(yīng)字段的功能。
接著我們來(lái)在類中使用相應(yīng)的元數(shù)據(jù):
class Greeter { @format("Hello, %s") name: string; constructor(name: string) { this.name = message; } sayHello() { let formatString = getFormat(this, "name"); return formatString.replace("%s", this.name); } } const g = new Greeter("Jony"); console.log(g.sayHello());
在上述中,我們?cè)趎ame屬性的裝飾器工廠函數(shù),執(zhí)行@format("Hello, %s"),返回一個(gè)裝飾器函數(shù),且該裝飾器函數(shù)修飾了Greeter類的name屬性,將“name”屬性的值寫入為"Hello, %s"。
然后再sayHello方法中,通過(guò)getFormat(this,"name")取到formatString為“Hello,%s”.
四、總結(jié)通過(guò)裝飾器,可以方便的修飾類,以及類的方法,類的屬性等,相比于繼承而言更加靈活,此外,通過(guò)注解的方法,可以在Typescript中引入元數(shù)據(jù),實(shí)現(xiàn)元編程等。特別是在angularjs、nestjs中,大量使用了注解,特別是nestjs構(gòu)建了類似于java springMVC式的web框架。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/100093.html
摘要:裝飾者模式裝飾者模式就是動(dòng)態(tài)的給類或?qū)ο笤黾庸δ艿脑O(shè)計(jì)模式。下的實(shí)現(xiàn)里的裝飾器目前處在建議征集的第二階段,不被瀏覽器所支持,如果想要提前使用這個(gè)新特性就需要,等工具進(jìn)行轉(zhuǎn)譯。這里介紹下的用法。 1.1、裝飾者模式 裝飾者模式就是動(dòng)態(tài)的給類或?qū)ο笤黾庸δ艿脑O(shè)計(jì)模式。在程序運(yùn)行時(shí)動(dòng)態(tài)的給一個(gè)具備基礎(chǔ)功能的類或?qū)ο筇砑有碌墓δ埽⑶也粫?huì)改變會(huì)破壞基礎(chǔ)類和對(duì)象的功能。先提煉出產(chǎn)品的最小可用產(chǎn)品...
摘要:使用裝飾器的方法很簡(jiǎn)單在裝飾器名前加字符,寫在想要裝飾的方法上,類似寫注釋的方式裝飾器實(shí)際上是一個(gè)函數(shù),入?yún)樗b飾的方法,返回值為裝飾后的方法。經(jīng)過(guò)裝飾過(guò)的方法,它依然按照原來(lái)的方式執(zhí)行,只是額外執(zhí)行了附件的裝飾器函數(shù)的功能。 讓我來(lái)深入地了解一下TypeScript對(duì)于裝飾器模式的實(shí)現(xiàn),以及反射與依賴注入等相關(guān)特性。 在Typescript的源代碼中,可以看到裝飾器能用來(lái)修飾cla...
摘要:新項(xiàng)目起手式最后更新于,技術(shù)文具有時(shí)效性,請(qǐng)知悉我知道你們?cè)缇拖胗蒙蠌?qiáng)類型了還有后續(xù)進(jìn)階篇安裝安裝依賴配置添加添加讓識(shí)別改造文件什么是是的強(qiáng)類型版本。是的超集,這意味著他支持所有的語(yǔ)法。與此同時(shí),也是的超集,的也宣布采用進(jìn)行開(kāi)發(fā)。 vue + typescript 新項(xiàng)目起手式 最后更新于2018-06-30,技術(shù)文具有時(shí)效性,請(qǐng)知悉 我知道你們?cè)缇拖胗蒙?vue + ts 強(qiáng)類型...
摘要:第二部分源碼解析接下是應(yīng)用多個(gè)第二部分對(duì)于一個(gè)方法應(yīng)用了多個(gè),比如會(huì)編譯為在第二部分的源碼中,執(zhí)行了和操作,由此我們也可以發(fā)現(xiàn),如果同一個(gè)方法有多個(gè)裝飾器,會(huì)由內(nèi)向外執(zhí)行。有了裝飾器,就可以改寫上面的代碼。 Decorator 裝飾器主要用于: 裝飾類 裝飾方法或?qū)傩? 裝飾類 @annotation class MyClass { } function annotation(ta...
閱讀 2724·2021-11-17 17:00
閱讀 2015·2021-10-11 10:57
閱讀 3846·2021-09-09 11:33
閱讀 1038·2021-09-09 09:33
閱讀 3616·2019-08-30 14:20
閱讀 3423·2019-08-29 11:25
閱讀 2874·2019-08-26 13:48
閱讀 818·2019-08-26 11:52