摘要:慶幸的是,已經(jīng)支持反射機制,來看看這個特性吧元數(shù)據(jù)反射可以通過安裝包來使用元數(shù)據(jù)反射的若要使用它,我們需要在中設(shè)置為,同時添加的引用,同時加載文件。復(fù)雜類型序列化的團隊為復(fù)雜類型的元數(shù)據(jù)序列化做出了努力。
本篇內(nèi)容包括如下部分:
為什么JavaScript中需要反射
元數(shù)據(jù)反射API
基本類型序列化
復(fù)雜類型序列化
為什么JavaScript中需要反射?關(guān)于反射的概念,摘自百度百科
在計算機科學(xué)領(lǐng)域,反射是指一類應(yīng)用,它們能夠自描述和自控制。也就是說,這類應(yīng)用通過采用某種機制來實現(xiàn)對自己行為的描述(self-representation)和監(jiān)測(examination),并能根據(jù)自身行為的狀態(tài)和結(jié)果,調(diào)整或修改應(yīng)用所描述行為的狀態(tài)和相關(guān)的語義。
可見反射機制對于依賴注入、運行時類型斷言、測試是非常有用的,同時隨著基于JavaScript的應(yīng)用做的越來越大,使得我們希望有一些工具和特性可以用來應(yīng)對增長的復(fù)雜度,例如控制反轉(zhuǎn),運行時類型斷言等。但由于JavaScript語言中沒有反射機制,所以導(dǎo)致這些東西要么沒法實現(xiàn),要么實現(xiàn)的不如C#或Java語言實現(xiàn)的強大。
強大的反射API允許我們可以在運行時測試一個未知的類,以及找到關(guān)于它的任何信息,包括:名稱、類型、接口等。雖然可以使用諸如Object.getOwnPropertyDescriptor()和Object.keys()查詢到一些信息,但我們需要反射來實現(xiàn)更強大的開發(fā)工具。慶幸的是,TypeScript已經(jīng)支持反射機制,來看看這個特性吧
元數(shù)據(jù)反射API可以通過安裝reflect-metadata包來使用元數(shù)據(jù)反射的API
npm install reflect-metadata;
若要使用它,我們需要在tsconfig.json中設(shè)置emitDecoratorMetadata為true,同時添加reflect-metadata.d.ts的引用,同時加載Reflect.js文件。然后我們來實現(xiàn)裝飾器并使用反射元數(shù)據(jù)設(shè)計的鍵值,目前可用的有:
類型元數(shù)據(jù):design:type
參數(shù)類型元數(shù)據(jù):design:paramtypes
返回類型元數(shù)據(jù):design:returntype
我們來通過一組例子來說明
1)獲取類型元數(shù)據(jù)首先聲明如下的屬性裝飾器:
function logType(target : any, key : string) { var t = Reflect.getMetadata("design:type", target, key); console.log(`${key} type: ${t.name}`); }
接下來將其應(yīng)用到一個類的屬性上,以獲取其類型:
class Demo{ @logType public attr1 : string; }
這個例子將會在控制臺中打印如下信息:
attr1 type: String2) 獲取參數(shù)類型元數(shù)據(jù)
聲明參數(shù)裝飾器如下:
function logParamTypes(target : any, key : string) { var types = Reflect.getMetadata("design:paramtypes", target, key); var s = types.map(a => a.name).join(); console.log(`${key} param types: ${s}`); }
然后將它應(yīng)用在一個類方法的參數(shù)上,用以獲取所裝飾參數(shù)的類型:
class Foo {} interface IFoo {} class Demo{ @logParameters param1 : string, param2 : number, param3 : Foo, param4 : { test : string }, param5 : IFoo, param6 : Function, param7 : (a : number) => void, ) : number { return 1 } }
這個例子的執(zhí)行結(jié)果是:
doSomething param types: String, Number, Foo, Object, Object, Function, Function3) 獲取返回類型元數(shù)據(jù)
同樣的我們可以使用"design:returntype"元數(shù)據(jù)鍵值,來獲取一個方法的返回類型:
Reflect.getMetadata("design:returntype", target, key);基本類型序列化
讓我們回看上面關(guān)于"design:paramtypes"的例子,注意到接口IFoo和對象字面量{test: string}被序列化為Object,這是因為TypeScript僅支持基本類型的序列化,基本類型序列化規(guī)則如下:
number序列化為Number
string序列化為String
boolean序列化為Boolean
any序列化為Object
void序列化為undefined
Array序列化為Array
元組Tuple序列化為Array
類class序列化為類的構(gòu)造函數(shù)
枚舉Enum序列化為Number
剩下的所有其他類型都被序列化為Object
接口和對象字面量可能在之后的復(fù)雜類型序列化中會被做具體的處理。
復(fù)雜類型序列化TypeScript的團隊為復(fù)雜類型的元數(shù)據(jù)序列化做出了努力。上面列出的序列化規(guī)則對基本類型依然適用,但對復(fù)雜類型提出了不同的序列化邏輯。如下是通過一個例子來描述所有可能的類型:
interface _Type { /** * Describes the specific shape of the type. * @remarks * One of: "typeparameter", "typereference", "interface", "tuple", "union" or "function". */ kind: string; }
我們也可以找到用于描述每種可能類型的類,例如用于序列化通用接口interface foo
// 描述一個通用接口 interface InterfaceType extends _Type { kind: string; // "interface" // 通用類型參數(shù). 可能為undefined. typeParameters?: TypeParameter[]; // 實現(xiàn)的接口. implements?: Type[]; // 類型的成員 可能為undefined. members?: { [key: string | symbol | number]: Type; }; // 類型的調(diào)用標(biāo)識. 可能為undefined. call?: Signature[]; // 類型的構(gòu)造標(biāo)識. 可能為undefined. construct?: Signature[]; // 類型的索引標(biāo)識. 可能為undefined. index?: Signature[]; }
這里有一個屬性指出實現(xiàn)了哪些接口
// 實現(xiàn)的接口 implements?: Type[];
這種信息可以用來在運行時驗證一個實例是否實現(xiàn)了特定的接口,而這個功能對于一個依賴翻轉(zhuǎn)容器特別的有用。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/101540.html
摘要:使用裝飾器的方法很簡單在裝飾器名前加字符,寫在想要裝飾的方法上,類似寫注釋的方式裝飾器實際上是一個函數(shù),入?yún)樗b飾的方法,返回值為裝飾后的方法。經(jīng)過裝飾過的方法,它依然按照原來的方式執(zhí)行,只是額外執(zhí)行了附件的裝飾器函數(shù)的功能。 讓我來深入地了解一下TypeScript對于裝飾器模式的實現(xiàn),以及反射與依賴注入等相關(guān)特性。 在Typescript的源代碼中,可以看到裝飾器能用來修飾cla...
摘要:可見參數(shù)裝飾器函數(shù)需要個參數(shù)被裝飾類的原型,裝飾參數(shù)所屬的方法名,參數(shù)的索引。參數(shù)裝飾器不應(yīng)當(dāng)用來修改構(gòu)造器方法或?qū)傩缘男袨椋粦?yīng)當(dāng)用來產(chǎn)生某種元數(shù)據(jù)。一旦元數(shù)據(jù)被創(chuàng)建,我們便可以用其它的裝飾器去讀取它。 之前已經(jīng)分別介紹了方法裝飾器、屬性裝飾器和類裝飾器,這篇文章我們來繼續(xù)關(guān)注這些話題: 參數(shù)裝飾器 裝飾器工廠 我們將圍繞以下這個例子,來探討這些概念: class Person...
摘要:值得注意的是,的返回值復(fù)寫了原始的構(gòu)造函數(shù),原因是類裝飾器必須返回一個構(gòu)造器函數(shù)。原始構(gòu)造函數(shù)的原型被復(fù)制給的原型,以確保在創(chuàng)建一個的新實例時,操作符如愿以償,具體原因可參考鄙人另一篇文章原型與對象。 上一篇文章中,我們討論了TypeScript源碼中關(guān)于方法裝飾器的實現(xiàn),搞明白了如下幾個問題: 裝飾器函數(shù)是如何被調(diào)用的? 裝飾器函數(shù)參數(shù)是如何傳入的? __decorate函數(shù)干了...
摘要:第章元編程與注解反射反射是在運行時獲取類的函數(shù)方法屬性父類接口注解元數(shù)據(jù)泛型信息等類的內(nèi)部信息的機制。本章介紹中的注解與反射編程的相關(guān)內(nèi)容。元編程本質(zhì)上是一種對源代碼本身進行高層次抽象的編碼技術(shù)。反射是促進元編程的一種很有價值的語言特性。 第12章 元編程與注解、反射 反射(Reflection)是在運行時獲取類的函數(shù)(方法)、屬性、父類、接口、注解元數(shù)據(jù)、泛型信息等類的內(nèi)部信息的機...
摘要:使用元數(shù)據(jù)包中包含了中每一個被建模類對應(yīng)的接口。任何對象的元數(shù)據(jù)是使用的實現(xiàn)來表示的。加載模型的序列化形式是個在運行期間獲取元數(shù)據(jù)的有效方法。反射提供一個反射式,可以檢查對象的元數(shù)據(jù)以及一般地訪問和操縱數(shù)據(jù)。 使用元數(shù)據(jù) Java包org.eclipse.emf.ecore中包含了Ecore中每一個被建模類對應(yīng)的接口。任何EMF對象的元數(shù)據(jù)是使用Ecore的實現(xiàn)(implement...
閱讀 1435·2021-11-25 09:43
閱讀 2041·2021-07-26 23:38
閱讀 748·2019-08-30 15:53
閱讀 2287·2019-08-30 15:43
閱讀 1176·2019-08-29 18:40
閱讀 1976·2019-08-26 13:28
閱讀 1982·2019-08-23 18:20
閱讀 551·2019-08-23 15:07