一問(wèn)了解JavaScript中的元數(shù)據(jù)
在 ES6
的規(guī)范當(dāng)中,ES6
支持元編程,核心是因?yàn)樘峁┝藢?duì) Proxy
和 Reflect
對(duì)象的支持,簡(jiǎn)單來(lái)說(shuō)這個(gè) API
的作用就是可以實(shí)現(xiàn)對(duì)變量操作的函數(shù)化,也就是反射。
元數(shù)據(jù)
什么是元數(shù)據(jù)
元數(shù)據(jù)是指附加在對(duì)象、類(lèi)、方法、屬性、參數(shù)上的數(shù)據(jù),它可以用來(lái)幫助實(shí)現(xiàn)某種業(yè)務(wù)功能需要用到的數(shù)據(jù)。
元數(shù)據(jù)的使用
Reflect-metadata-
是 ES7
的一個(gè)提案,它主要用來(lái)聲明的時(shí)候添加和讀取元數(shù)據(jù),Typescript
在 1.5+
的版本已經(jīng)支持它,你只需要:
npm i reflect-metadata --save
緊接著你要在 tsconfig.json
文件中添加以下配置:
{ "compilerOptions": { "emitDecoratorMetadata": true, "experimentalDecorators": true } }
defineMetadata() 和 getMetadata()
該方法是一個(gè)函數(shù)重載,它既可以接收三個(gè)參數(shù),也可以是四個(gè)參數(shù),具體定義如下所示:
function defineMetadata(metadataKey: any, metadataValue: any, target: Object): void; function defineMetadata(metadataKey: any, metadataValue: any, target: Object, propertyKey: string | symbol): void;
它們的參數(shù)分別是:
metadataKey
: 用于存儲(chǔ)和檢索元數(shù)據(jù)的鍵;metadataValue
: 元數(shù)據(jù)的值;target
: 要在其上定義元數(shù)據(jù)的目標(biāo)對(duì)象;propertyKey
: 目標(biāo)對(duì)象上的屬性;
有存值的就有取值的,這個(gè)方法也是一個(gè)函數(shù)重載,它的具體定義如下所示:
function getMetadata(metadataKey: any, target: Object, propertyKey: string | symbol): any; function getOwnMetadata(metadataKey: any, target: Object): any;
它的具體使用如下所示:
import "reflect-metadata"; const moment = { address: "廣州" }; Reflect.defineMetadata("method", "hi,叼毛,你上班是不是在摸魚(yú)", moment); console.log(Reflect.getMetadata("method", moment)); // hi,叼毛,你上班是不是在摸魚(yú) Reflect.defineMetadata("method", "hi,靚仔,買(mǎi)菜嗎", moment, moment.address); console.log(Reflect.getMetadata("method", moment, moment.address)); // hi,靚仔,買(mǎi)菜嗎
metadata()
Reflect.metadata(...)
方法的可以用于類(lèi)或者類(lèi)屬性上,它的具體定義如下所示:
function metadata( metadataKey: any, metadataValue: any ): { (target: Function): void; (target: Object, propertyKey: string | symbol): void; };
Reflect.metadata
當(dāng)作 Decorator
使用,當(dāng)修飾類(lèi)時(shí),在類(lèi)上添加元數(shù)據(jù),當(dāng)修飾類(lèi)屬性時(shí),在類(lèi)原型的屬性上添加元數(shù)據(jù):
import "reflect-metadata"; @Reflect.metadata("inClass", "哇哈哈哈哈") class Test { @Reflect.metadata("inMethod", "我要喝喜之郎,我要當(dāng)太空人") public hello(): string { return "hello world"; } } console.log(Reflect.getMetadata("inClass", Test)); // 哇哈哈哈哈 console.log(Reflect.getMetadata("inMethod", new Test(), "hello")); // 我要喝喜之郎,我要當(dāng)太空人
在這里可能會(huì)有人就好奇了,這里面的方法怎么和上面的不一樣啊,上面的是 defineMetadata(...)
,而這里直接用的 metadata(...)
,這是為什么呢?
答案是 defineMetadata(...)
它要確定你要是在哪里定義的元數(shù)據(jù),而后者是直接以裝飾器的方式調(diào)用,它已經(jīng)明確知道了你就是給這個(gè)類(lèi)來(lái)定義的元數(shù)據(jù)。
獲取類(lèi)型信息并賦值
我們可以通過(guò) Reflect.getMetadata
方法來(lái)獲取屬性類(lèi)型,并且對(duì)該屬性進(jìn)行賦值,如下操作所示:
import "reflect-metadata"; function Prop(): PropertyDecorator { return (target, key: string) => { const type = Reflect.getMetadata("design:type", target, key); console.log(`${key} type: ${type.name}`); target[key] = "moment"; }; } class SomeClass { @Prop() public nickname!: string; } console.log(new SomeClass().nickname); // moment
例如在 vue-property-decorator
中通過(guò)使用 Reflect.getMetadata
API,Prop
Decorator 能獲取屬性類(lèi)型傳至 Vue
,簡(jiǎn)要代碼如下:
import { Vue, Component, PropSync } from 'vue-property-decorator' @Component export default class YourComponent extends Vue { @PropSync('name', { type: String }) syncedName!: string }
這樣的寫(xiě)法就等同于以下代碼所示:
export default { props: { name: { type: String, }, }, computed: { syncedName: { get() { return this.name }, set(value) { this.$emit('update:name', value) }, }, }, }
除了能獲取屬性類(lèi)型以外,通過(guò) Reflect.getMetadata("design:paramtypes", target, key)
和 Reflect.getMetadata("design:returntype", target, key)
可以分別獲取函數(shù)參數(shù)類(lèi)型和返回值類(lèi)型,具體代碼如下所示:
import "reflect-metadata"; function Func(): PropertyDecorator { return (target, key: string) => { console.log(Reflect.getMetadata("design:paramtypes", target, key)); // 函數(shù)參數(shù)類(lèi)型 console.log(Reflect.getMetadata("design:returntype", target, key)); // 返回值類(lèi)型 }; } class SomeClass { @Func() moment(value: boolean): string { return " "; } }
自定義 metadataKey
除了能獲取類(lèi)型信息外,常用與自定義 metadataKey
,并在合適的實(shí)際獲取它的值,具體實(shí)例代碼如下所示:
import "reflect-metadata"; function classDecorator(): ClassDecorator { return (target) => { Reflect.defineMetadata("class", "類(lèi)裝飾器", target); }; } function methodDecorator(): MethodDecorator { return (target, key, descriptor) => { Reflect.defineMetadata("method", "方法裝飾器", target, key); }; } @classDecorator() class SomeClass { @methodDecorator() someMethod() {} } console.log(Reflect.getMetadata("class", SomeClass)); // 類(lèi)裝飾器 console.log(Reflect.getMetadata("method", new SomeClass(), "someMethod")); // 方法裝飾器
參考文獻(xiàn)
總結(jié)
元數(shù)據(jù)的應(yīng)用場(chǎng)景很多,其中 NestJs
就是使用了大量的元數(shù)組實(shí)現(xiàn)了控制反轉(zhuǎn)和依賴(lài)注入,將會(huì)在下一篇文章中講到,本篇文章到此結(jié)束。
到此這篇關(guān)于一問(wèn)了解JavaScript中的元數(shù)據(jù)的文章就介紹到這了,更多相關(guān)JavaScript 元數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js操作DOM--添加、刪除節(jié)點(diǎn)的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇js操作DOM--添加、刪除節(jié)點(diǎn)的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07微信小程序?qū)W習(xí)筆記之表單提交與PHP后臺(tái)數(shù)據(jù)交互處理圖文詳解
這篇文章主要介紹了微信小程序?qū)W習(xí)筆記之表單提交與PHP后臺(tái)數(shù)據(jù)交互處理,結(jié)合實(shí)例形式詳細(xì)分析了微信小程序前臺(tái)數(shù)據(jù)form表單提交及后臺(tái)使用php進(jìn)行處理相關(guān)操作技巧,并配以圖文形式詳細(xì)說(shuō)明,需要的朋友可以參考下2019-03-03Javascript數(shù)組及類(lèi)數(shù)組相關(guān)原理詳解
這篇文章主要介紹了Javascript數(shù)組及類(lèi)數(shù)組相關(guān)原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10原生JS實(shí)現(xiàn)獲取及修改CSS樣式的方法
這篇文章主要介紹了原生JS實(shí)現(xiàn)獲取及修改CSS樣式的方法,結(jié)合實(shí)例形式簡(jiǎn)單分析了JavaScript針對(duì)頁(yè)面元素屬性動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-09-09JavaScript正則表達(dá)式小結(jié)(test|match|search|replace|split|exec)
這篇文章主要介紹了JavaScript正則表達(dá)式小結(jié)(test|match|search|replace|split|exec)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2016-12-12JS實(shí)現(xiàn)將二維數(shù)組轉(zhuǎn)為json格式字符串操作示例
這篇文章主要介紹了JS實(shí)現(xiàn)將二維數(shù)組轉(zhuǎn)為json格式字符串操作,涉及javascript數(shù)組遍歷、拼接、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下2018-07-07由JavaScript技術(shù)實(shí)現(xiàn)的web小游戲(不含網(wǎng)游)
伴隨Ajax與網(wǎng)頁(yè)游戲的崛起,曾幾何時(shí)JavaScript也成了游戲開(kāi)發(fā)時(shí)可供選擇的技術(shù)之一,文本 僅列舉數(shù)項(xiàng)由JavaScript技術(shù)實(shí)現(xiàn)的web小游戲(不含網(wǎng)游),聊作參考之用。2010-06-06javascript中RegExp保留小數(shù)點(diǎn)后幾位數(shù)的方法分享
文章介紹一篇關(guān)于javascript中RegExp保留小數(shù)點(diǎn)后幾位數(shù)方法,有需要了解的朋友可以參考一下2013-08-08