浅入浅出Typescript Decorators
臨時(shí)起的興趣,想寫(xiě)一篇關(guān)于ts decorator的文章,就花小半天整理了一下... 
這東西,在ES2017里好像也有... 文檔的話看這里。
因?yàn)榕R時(shí),也沒(méi)想寫(xiě)太多文字介紹,帶少許文字說(shuō)明直接開(kāi)擼代碼吧。
本文通過(guò)ts編譯后的decorator代碼解釋一番裝飾器是什么?能做什么?有什么好處?
實(shí)現(xiàn)代碼
編譯后代碼是這樣的,帶注釋:
var __decorate =(this && this.__decorate) ||function(decorators, target, key, desc) {// c 參數(shù)長(zhǎng)度// r ? c < 3 則是target,否則先判斷desc為null的話則將desc取target的key屬性的描述,再否則便是desc了// d 預(yù)留使用var c = arguments.length,r =c < 3? target: desc === null? (desc = Object.getOwnPropertyDescriptor(target, key)): desc,d;// 下面文字解釋,這僅是個(gè)甩鍋的行為if (typeof Reflect === "object" && typeof Reflect.decorate === "function")r = Reflect.decorate(decorators, target, key, desc);// 循環(huán) decorators 并每次賦值給 d,并且判斷值elsefor (var i = decorators.length - 1; i >= 0; i--)if ((d = decorators[i]))// c < 3 ,用 r 作為 decorators[i] 的入?yún)?zhí)行;// c > 3 ,target, key, r 作為 decorators[i] 的入?yún)?zhí)行;// c === 3,target, key 作為 decorators[i] 的入?yún)?zhí)行。// 如果執(zhí)行無(wú)返回結(jié)果, r = r;。r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;// 如果 c > 3 && r , 修改 target ,返回 rreturn c > 3 && r && Object.defineProperty(target, key, r), r;};從代碼里可以看出,最終結(jié)果要么是用decorator執(zhí)行target,從而改變一些什么東西;要么就是使用Object.defineProperty來(lái)對(duì)target來(lái)做操作,代碼就幾行,用處確不小...具體的執(zhí)行過(guò)程結(jié)合下面的兩個(gè)例子會(huì)更容易理解。
值得一提的是,關(guān)于代碼里的Reflect原本以為是這個(gè) sec-reflect-object 里的方法,但可惜不是;
然后猜測(cè)是Typescript的實(shí)現(xiàn),翻了Typescript/tsc.js的代碼(如果打不開(kāi)鏈接就從 node_modules 下看吧),發(fā)現(xiàn)也不是,再去查 stackoverflow 的解釋,是這樣的 what-is-reflect-decorate-in-js-code-transpiled-from-ts
大致說(shuō)是ts希望把這個(gè)鍋甩給ES來(lái)補(bǔ),到時(shí)候ts的else里的代碼便是polyfill了
案例
以下面的 decorator 和 class 作為例子解釋
// ts 代碼 function show(target: any) {console.log(target);target.prototype.showMe = (name: string) => {console.log("show me :", name);}; }interface IShow {showMe?(name: string): any; }@show class Show implements IShow {showMe(name: string) {} }const shoow = new Show(); shoow.showMe("ys");// 編譯后的js // decorator ,簡(jiǎn)單的打印,并且修改方法 function show(target) {console.log(target);target.prototype.showMe = function(name) {console.log("show me :", name);}; }// class Shoow var Shoow = (function() {function Shoow() {}Shoow.prototype.showMe = function(name) {};// decorators 為[show],target 為 ShoowShoow = __decorate([show], Shoow);return Shoow; })();var shooow = new Shoow(); shooow.showMe("ys");// output : show me : ys理解一下執(zhí)行步驟:
一個(gè)不夠?再來(lái)一個(gè)?這次在里面返回一個(gè)函數(shù)試試?
// ts代碼 function logger1(config?) {return function(target, key: string, descriptor: PropertyDescriptor) {const _value = descriptor.value;if (typeof _value === "function") {descriptor.value = (...args) => {console.log(`logger1-begin : ${config.level}`);const res = _value.apply(target, args);console.log(`logger1-end`);return res;};}return descriptor;}; }function logger2(config?) {return function(target, key: string, descriptor: PropertyDescriptor) {const _value = descriptor.value;if (typeof _value === "function") {descriptor.value = (...args) => {console.log(`logger2-begin : ${config.level}`);const res = _value.apply(target, args);console.log(`logger2-end`);return res;};}return descriptor;}; }interface IShow {showMe?(name: string): any; }class Show implements IShow {@logger1({ level: "info" })@logger2({ level: "error" })showMe(name: string) {console.log("show me :", name);} }const shoow = new Show(); shoow.showMe("ys");// output 這里手動(dòng)加個(gè)縮進(jìn),這時(shí)候showMe方法已經(jīng)經(jīng)過(guò)多次包裹 // logger1-begin : info // logger2-begin : error // show me : ys // logger2-end // logger1-end再來(lái)看看執(zhí)行步驟:
歡樂(lè)
裝飾器給你帶來(lái)什么歡樂(lè)?簡(jiǎn)單列幾個(gè)最明顯的優(yōu)點(diǎn),其他在運(yùn)用中各自提取每日份的快樂(lè)去吧...
最后
AOP,了解一下
總結(jié)
以上是生活随笔為你收集整理的浅入浅出Typescript Decorators的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: [转] iphoneX、iphoneXS
- 下一篇: 小猿搜题在线立即使用(3699在线小游戏
