javascript
JS 中的装饰器
js 中的裝飾器還是一個(gè)提案,需要 babel 才可以使用。它還是一項(xiàng)實(shí)驗(yàn)性特性,在未來(lái)的版本中可能會(huì)發(fā)生改變。
裝飾器是一個(gè)函數(shù),它只能作用于類不能作用于(因?yàn)楹瘮?shù)提升),它以一個(gè)@符號(hào)開頭,如下:
function d(target) { return target }@d class A {}// 它相當(dāng)于把類作為參數(shù)傳遞給 d 函數(shù),然后再返回一個(gè)被函數(shù)修改過的類 // 等同于 A = d(A) || A 復(fù)制代碼它還可以傳遞自定義參數(shù)和使用多個(gè)裝飾器
function a(p) {console.log(1)return (target => {console.log(2)return target}) } function b(target) {console.log(3)return target }@b @a(1) class A {}// 打印順序是 1 2 3 復(fù)制代碼多個(gè)裝飾器除了一行寫一個(gè),也可以全都寫在一行@b @a(1)。
在 react-redux 應(yīng)用中使用裝飾器可以這樣使用 connect 方法
@connect(mapStateToProps, mapDispatchToProps) export default class Comp extends Component {} 復(fù)制代碼方法的裝飾
裝飾器除了作用于類,還可以作用于類的方法。
function d(target, name, desc) {// target 是類的原型對(duì)象// name 是函數(shù)的名字// desc 是屬性描述符let oldValue = desc.value;desc.value = function() {console.log(`Calling ${name} with`, arguments);return oldValue.apply(this, arguments);};return desc// 如果方法裝飾器返回一個(gè)值,它會(huì)被用作方法的屬性描述符。 }class A {@dfn () {} } 復(fù)制代碼在 TypeScript 中方法裝飾器的 target 參數(shù),對(duì)于靜態(tài)成員來(lái)說是類的構(gòu)造函數(shù),對(duì)于實(shí)例成員是類的原型對(duì)象。
屬性裝飾器
在 TypeScript 中裝飾器還可以作用于屬性。
function d(target, name) {// target 對(duì)于靜態(tài)成員來(lái)說是類的構(gòu)造函數(shù),對(duì)于實(shí)例成員是類的原型對(duì)象。// name 屬性的名字 }class A() {@dgreeting: string; } 復(fù)制代碼參數(shù)裝飾器
TypeScript 中還可以裝飾參數(shù),
function Query(target, name, index) {// target 對(duì)于靜態(tài)成員來(lái)說是類的構(gòu)造函數(shù),對(duì)于實(shí)例成員是類的原型對(duì)象// name 方法的函數(shù)名// index 參數(shù)的索引 從 0 開始// 參數(shù)裝飾器的返回值會(huì)被忽略。 }class A() {fn(@Query query: Object) {} } 復(fù)制代碼存取裝飾器
TypeScript 中裝飾器也可以裝飾存取聲明函數(shù)。
function d(target, name, desc) {// target 對(duì)于靜態(tài)成員來(lái)說是類的構(gòu)造函數(shù),對(duì)于實(shí)例成員是類的原型對(duì)象// name 函數(shù)名// desc 屬性描述符return desc// 如果方法裝飾器返回一個(gè)值,它會(huì)被用作屬性描述符 }class A() {@dget a() {} } 復(fù)制代碼裝飾器求值
TypeScript 多個(gè)裝飾器執(zhí)行順序是,
是從里到外的執(zhí)行順序。
元數(shù)據(jù)
reflect-metadata 庫(kù)是來(lái)支持實(shí)驗(yàn)性的metadata API,這個(gè)庫(kù)還不是ECMAScript (JavaScript)標(biāo)準(zhǔn)的一部分。
要使用元數(shù)據(jù)需要先開啟experimentalDecorators emitDecoratorMetadata選項(xiàng)。
當(dāng)啟用后,只要reflect-metadata庫(kù)被引入了,設(shè)計(jì)階段添加的類型信息可以在運(yùn)行時(shí)使用。
function D(...rest) {}class A {@Dreadonly a: string; }class B {fn(@D x: A) {console.log(x)} } 復(fù)制代碼會(huì)被轉(zhuǎn)義成
function D(...rest) { } class A { } __decorate([D,__metadata("design:type", String) ], A.prototype, "a", void 0); class B {fn(x) {console.log(x);} } __decorate([__param(0, D),__metadata("design:type", Function),__metadata("design:paramtypes", [A]),__metadata("design:returntype", void 0) ], B.prototype, "fn", null); 復(fù)制代碼它加入了__metadata函數(shù),將裝飾器的元信息存取起來(lái),這樣就可以隨時(shí)獲取出來(lái)。
nodejs 的 nestjs 框架就大量使用到了這些元信息。
轉(zhuǎn)載于:https://juejin.im/post/5c77f0f1518825629f387207
總結(jié)
- 上一篇: 【Laravel-海贼王系列】第十三章,
- 下一篇: ScrollView(RecyclerV